Milestone 5: deliver embedded RDP sessions and lifecycle hardening
This commit is contained in:
22
third_party/FreeRDP/winpr/libwinpr/file/CMakeLists.txt
vendored
Normal file
22
third_party/FreeRDP/winpr/libwinpr/file/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# WinPR: Windows Portable Runtime
|
||||
# libwinpr-file cmake build script
|
||||
#
|
||||
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
winpr_module_add(generic.c namedPipeClient.c namedPipeClient.h pattern.c file.c)
|
||||
|
||||
if(BUILD_TESTING_INTERNAL OR BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
9
third_party/FreeRDP/winpr/libwinpr/file/ModuleOptions.cmake
vendored
Normal file
9
third_party/FreeRDP/winpr/libwinpr/file/ModuleOptions.cmake
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
set(MINWIN_LAYER "1")
|
||||
set(MINWIN_GROUP "core")
|
||||
set(MINWIN_MAJOR_VERSION "2")
|
||||
set(MINWIN_MINOR_VERSION "0")
|
||||
set(MINWIN_SHORT_NAME "file")
|
||||
set(MINWIN_LONG_NAME "File Functions")
|
||||
set(MODULE_LIBRARY_NAME
|
||||
"api-ms-win-${MINWIN_GROUP}-${MINWIN_SHORT_NAME}-l${MINWIN_LAYER}-${MINWIN_MAJOR_VERSION}-${MINWIN_MINOR_VERSION}"
|
||||
)
|
||||
1581
third_party/FreeRDP/winpr/libwinpr/file/file.c
vendored
Normal file
1581
third_party/FreeRDP/winpr/libwinpr/file/file.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
66
third_party/FreeRDP/winpr/libwinpr/file/file.h
vendored
Normal file
66
third_party/FreeRDP/winpr/libwinpr/file/file.h
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* File Functions
|
||||
*
|
||||
* Copyright 2015 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2015 Thincast Technologies GmbH
|
||||
* Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WINPR_FILE_PRIV_H
|
||||
#define WINPR_FILE_PRIV_H
|
||||
|
||||
#include <winpr/winpr.h>
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
#include <winpr/nt.h>
|
||||
#include <winpr/io.h>
|
||||
#include <winpr/error.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <stdio.h>
|
||||
#include "../handle/handle.h"
|
||||
|
||||
#define EPOCH_DIFF 11644473600LL
|
||||
#define STAT_TIME_TO_FILETIME(_t) (((UINT64)(_t) + EPOCH_DIFF) * 10000000LL)
|
||||
|
||||
struct winpr_file
|
||||
{
|
||||
WINPR_HANDLE common;
|
||||
|
||||
FILE* fp;
|
||||
|
||||
char* lpFileName;
|
||||
|
||||
DWORD dwOpenMode;
|
||||
DWORD dwShareMode;
|
||||
DWORD dwFlagsAndAttributes;
|
||||
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes;
|
||||
DWORD dwCreationDisposition;
|
||||
HANDLE hTemplateFile;
|
||||
|
||||
BOOL bLocked;
|
||||
};
|
||||
typedef struct winpr_file WINPR_FILE;
|
||||
|
||||
const HANDLE_CREATOR* GetFileHandleCreator(void);
|
||||
|
||||
UINT32 map_posix_err(int fs_errno);
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#endif /* WINPR_FILE_PRIV_H */
|
||||
1377
third_party/FreeRDP/winpr/libwinpr/file/generic.c
vendored
Normal file
1377
third_party/FreeRDP/winpr/libwinpr/file/generic.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
286
third_party/FreeRDP/winpr/libwinpr/file/namedPipeClient.c
vendored
Normal file
286
third_party/FreeRDP/winpr/libwinpr/file/namedPipeClient.c
vendored
Normal file
@@ -0,0 +1,286 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* File Functions
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
* Copyright 2015 Thincast Technologies GmbH
|
||||
* Copyright 2015 bernhard.miklautz@thincast.com
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/file.h>
|
||||
|
||||
#ifdef WINPR_HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "../log.h"
|
||||
#define TAG WINPR_TAG("file")
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <sys/vfs.h>
|
||||
#else
|
||||
#include <sys/statvfs.h>
|
||||
#endif
|
||||
|
||||
#include "../handle/handle.h"
|
||||
|
||||
#include "../pipe/pipe.h"
|
||||
#include "namedPipeClient.h"
|
||||
|
||||
static BOOL NamedPipeClientIsHandled(HANDLE handle)
|
||||
{
|
||||
return WINPR_HANDLE_IS_HANDLED(handle, HANDLE_TYPE_NAMED_PIPE, TRUE);
|
||||
}
|
||||
|
||||
static BOOL NamedPipeClientCloseHandle(HANDLE handle)
|
||||
{
|
||||
WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*)handle;
|
||||
|
||||
if (!NamedPipeClientIsHandled(handle))
|
||||
return FALSE;
|
||||
|
||||
if (pNamedPipe->clientfd != -1)
|
||||
{
|
||||
// WLOG_DBG(TAG, "closing clientfd %d", pNamedPipe->clientfd);
|
||||
close(pNamedPipe->clientfd);
|
||||
}
|
||||
|
||||
if (pNamedPipe->serverfd != -1)
|
||||
{
|
||||
// WLOG_DBG(TAG, "closing serverfd %d", pNamedPipe->serverfd);
|
||||
close(pNamedPipe->serverfd);
|
||||
}
|
||||
|
||||
if (pNamedPipe->pfnUnrefNamedPipe)
|
||||
pNamedPipe->pfnUnrefNamedPipe(pNamedPipe);
|
||||
|
||||
free(pNamedPipe->lpFileName);
|
||||
free(pNamedPipe->lpFilePath);
|
||||
free(pNamedPipe->name);
|
||||
free(pNamedPipe);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int NamedPipeClientGetFd(HANDLE handle)
|
||||
{
|
||||
WINPR_NAMED_PIPE* file = (WINPR_NAMED_PIPE*)handle;
|
||||
|
||||
if (!NamedPipeClientIsHandled(handle))
|
||||
return -1;
|
||||
|
||||
if (file->ServerMode)
|
||||
return file->serverfd;
|
||||
else
|
||||
return file->clientfd;
|
||||
}
|
||||
|
||||
static HANDLE_OPS ops = {
|
||||
NamedPipeClientIsHandled,
|
||||
NamedPipeClientCloseHandle,
|
||||
NamedPipeClientGetFd,
|
||||
nullptr, /* CleanupHandle */
|
||||
NamedPipeRead,
|
||||
nullptr, /* FileReadEx */
|
||||
nullptr, /* FileReadScatter */
|
||||
NamedPipeWrite,
|
||||
nullptr, /* FileWriteEx */
|
||||
nullptr, /* FileWriteGather */
|
||||
nullptr, /* FileGetFileSize */
|
||||
nullptr, /* FlushFileBuffers */
|
||||
nullptr, /* FileSetEndOfFile */
|
||||
nullptr, /* FileSetFilePointer */
|
||||
nullptr, /* SetFilePointerEx */
|
||||
nullptr, /* FileLockFile */
|
||||
nullptr, /* FileLockFileEx */
|
||||
nullptr, /* FileUnlockFile */
|
||||
nullptr, /* FileUnlockFileEx */
|
||||
nullptr, /* SetFileTime */
|
||||
nullptr, /* FileGetFileInformationByHandle */
|
||||
};
|
||||
|
||||
static HANDLE
|
||||
NamedPipeClientCreateFileA(LPCSTR lpFileName, WINPR_ATTR_UNUSED DWORD dwDesiredAccess,
|
||||
WINPR_ATTR_UNUSED DWORD dwShareMode,
|
||||
WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
WINPR_ATTR_UNUSED DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes, WINPR_ATTR_UNUSED HANDLE hTemplateFile)
|
||||
{
|
||||
int status = 0;
|
||||
struct sockaddr_un s = WINPR_C_ARRAY_INIT;
|
||||
|
||||
if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
|
||||
{
|
||||
WLog_ERR(TAG, "WinPR does not support the FILE_FLAG_OVERLAPPED flag");
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (!lpFileName)
|
||||
return INVALID_HANDLE_VALUE;
|
||||
|
||||
if (!IsNamedPipeFileNameA(lpFileName))
|
||||
return INVALID_HANDLE_VALUE;
|
||||
|
||||
WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*)calloc(1, sizeof(WINPR_NAMED_PIPE));
|
||||
|
||||
if (!pNamedPipe)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
HANDLE hNamedPipe = (HANDLE)pNamedPipe;
|
||||
WINPR_HANDLE_SET_TYPE_AND_MODE(pNamedPipe, HANDLE_TYPE_NAMED_PIPE, WINPR_FD_READ);
|
||||
pNamedPipe->name = _strdup(lpFileName);
|
||||
|
||||
if (!pNamedPipe->name)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pNamedPipe->dwOpenMode = 0;
|
||||
pNamedPipe->dwPipeMode = 0;
|
||||
pNamedPipe->nMaxInstances = 0;
|
||||
pNamedPipe->nOutBufferSize = 0;
|
||||
pNamedPipe->nInBufferSize = 0;
|
||||
pNamedPipe->nDefaultTimeOut = 0;
|
||||
pNamedPipe->dwFlagsAndAttributes = dwFlagsAndAttributes;
|
||||
pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpFileName);
|
||||
|
||||
if (!pNamedPipe->lpFileName)
|
||||
goto fail;
|
||||
|
||||
pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpFileName);
|
||||
|
||||
if (!pNamedPipe->lpFilePath)
|
||||
goto fail;
|
||||
|
||||
pNamedPipe->clientfd = socket(PF_LOCAL, SOCK_STREAM, 0);
|
||||
if (pNamedPipe->clientfd < 0)
|
||||
goto fail;
|
||||
|
||||
pNamedPipe->serverfd = -1;
|
||||
pNamedPipe->ServerMode = FALSE;
|
||||
s.sun_family = AF_UNIX;
|
||||
(void)sprintf_s(s.sun_path, ARRAYSIZE(s.sun_path), "%s", pNamedPipe->lpFilePath);
|
||||
status = connect(pNamedPipe->clientfd, (struct sockaddr*)&s, sizeof(struct sockaddr_un));
|
||||
pNamedPipe->common.ops = &ops;
|
||||
|
||||
if (status != 0)
|
||||
goto fail;
|
||||
|
||||
if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
|
||||
{
|
||||
// TODO: Implement
|
||||
WLog_ERR(TAG, "TODO: implement this");
|
||||
}
|
||||
|
||||
return hNamedPipe;
|
||||
|
||||
fail:
|
||||
if (pNamedPipe)
|
||||
{
|
||||
if (pNamedPipe->clientfd >= 0)
|
||||
close(pNamedPipe->clientfd);
|
||||
free(pNamedPipe->name);
|
||||
free(pNamedPipe->lpFileName);
|
||||
free(pNamedPipe->lpFilePath);
|
||||
free(pNamedPipe);
|
||||
}
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
const HANDLE_CREATOR* GetNamedPipeClientHandleCreator(void)
|
||||
{
|
||||
static const HANDLE_CREATOR NamedPipeClientHandleCreator = { .IsHandled = IsNamedPipeFileNameA,
|
||||
.CreateFileA =
|
||||
NamedPipeClientCreateFileA };
|
||||
return &NamedPipeClientHandleCreator;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Extended API */
|
||||
|
||||
#define NAMED_PIPE_PREFIX_PATH "\\\\.\\pipe\\"
|
||||
|
||||
BOOL IsNamedPipeFileNameA(LPCSTR lpName)
|
||||
{
|
||||
return (strncmp(lpName, NAMED_PIPE_PREFIX_PATH, sizeof(NAMED_PIPE_PREFIX_PATH) - 1) == 0);
|
||||
}
|
||||
|
||||
char* GetNamedPipeNameWithoutPrefixA(LPCSTR lpName)
|
||||
{
|
||||
char* lpFileName = nullptr;
|
||||
|
||||
if (!lpName)
|
||||
return nullptr;
|
||||
|
||||
if (!IsNamedPipeFileNameA(lpName))
|
||||
return nullptr;
|
||||
|
||||
lpFileName = _strdup(&lpName[strnlen(NAMED_PIPE_PREFIX_PATH, sizeof(NAMED_PIPE_PREFIX_PATH))]);
|
||||
return lpFileName;
|
||||
}
|
||||
|
||||
char* GetNamedPipeUnixDomainSocketBaseFilePathA(void)
|
||||
{
|
||||
char* lpTempPath = nullptr;
|
||||
char* lpPipePath = nullptr;
|
||||
lpTempPath = GetKnownPath(KNOWN_PATH_TEMP);
|
||||
|
||||
if (!lpTempPath)
|
||||
return nullptr;
|
||||
|
||||
lpPipePath = GetCombinedPath(lpTempPath, ".pipe");
|
||||
free(lpTempPath);
|
||||
return lpPipePath;
|
||||
}
|
||||
|
||||
char* GetNamedPipeUnixDomainSocketFilePathA(LPCSTR lpName)
|
||||
{
|
||||
char* lpPipePath = nullptr;
|
||||
char* lpFileName = nullptr;
|
||||
char* lpFilePath = nullptr;
|
||||
lpPipePath = GetNamedPipeUnixDomainSocketBaseFilePathA();
|
||||
lpFileName = GetNamedPipeNameWithoutPrefixA(lpName);
|
||||
lpFilePath = GetCombinedPath(lpPipePath, lpFileName);
|
||||
free(lpPipePath);
|
||||
free(lpFileName);
|
||||
return lpFilePath;
|
||||
}
|
||||
|
||||
int GetNamePipeFileDescriptor(HANDLE hNamedPipe)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
int fd = 0;
|
||||
WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*)hNamedPipe;
|
||||
|
||||
if (!NamedPipeClientIsHandled(hNamedPipe))
|
||||
return -1;
|
||||
|
||||
fd = (pNamedPipe->ServerMode) ? pNamedPipe->serverfd : pNamedPipe->clientfd;
|
||||
return fd;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
25
third_party/FreeRDP/winpr/libwinpr/file/namedPipeClient.h
vendored
Normal file
25
third_party/FreeRDP/winpr/libwinpr/file/namedPipeClient.h
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* File Functions
|
||||
*
|
||||
* Copyright 2024 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2024 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <winpr/file.h>
|
||||
|
||||
extern const HANDLE_CREATOR* GetNamedPipeClientHandleCreator(void);
|
||||
373
third_party/FreeRDP/winpr/libwinpr/file/pattern.c
vendored
Normal file
373
third_party/FreeRDP/winpr/libwinpr/file/pattern.c
vendored
Normal file
@@ -0,0 +1,373 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* File Functions
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/handle.h>
|
||||
|
||||
#include <winpr/file.h>
|
||||
|
||||
#ifdef WINPR_HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef WINPR_HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "../log.h"
|
||||
#define TAG WINPR_TAG("file")
|
||||
|
||||
/**
|
||||
* File System Behavior in the Microsoft Windows Environment:
|
||||
* http://download.microsoft.com/download/4/3/8/43889780-8d45-4b2e-9d3a-c696a890309f/File%20System%20Behavior%20Overview.pdf
|
||||
*/
|
||||
|
||||
LPSTR FilePatternFindNextWildcardA(LPCSTR lpPattern, DWORD* pFlags)
|
||||
{
|
||||
LPSTR lpWildcard = nullptr;
|
||||
*pFlags = 0;
|
||||
lpWildcard = strpbrk(lpPattern, "*?~");
|
||||
|
||||
if (lpWildcard)
|
||||
{
|
||||
if (*lpWildcard == '*')
|
||||
{
|
||||
*pFlags = WILDCARD_STAR;
|
||||
return lpWildcard;
|
||||
}
|
||||
else if (*lpWildcard == '?')
|
||||
{
|
||||
*pFlags = WILDCARD_QM;
|
||||
return lpWildcard;
|
||||
}
|
||||
else if (*lpWildcard == '~')
|
||||
{
|
||||
if (lpWildcard[1] == '*')
|
||||
{
|
||||
*pFlags = WILDCARD_DOS_STAR;
|
||||
return lpWildcard;
|
||||
}
|
||||
else if (lpWildcard[1] == '?')
|
||||
{
|
||||
*pFlags = WILDCARD_DOS_QM;
|
||||
return lpWildcard;
|
||||
}
|
||||
else if (lpWildcard[1] == '.')
|
||||
{
|
||||
*pFlags = WILDCARD_DOS_DOT;
|
||||
return lpWildcard;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static BOOL FilePatternMatchSubExpressionA(LPCSTR lpFileName, size_t cchFileName, LPCSTR lpX,
|
||||
size_t cchX, LPCSTR lpY, size_t cchY, LPCSTR lpWildcard,
|
||||
LPCSTR* ppMatchEnd)
|
||||
{
|
||||
LPCSTR lpMatch = nullptr;
|
||||
|
||||
if (!lpFileName)
|
||||
return FALSE;
|
||||
|
||||
if (*lpWildcard == '*')
|
||||
{
|
||||
/*
|
||||
* S
|
||||
* <-----<
|
||||
* X | | e Y
|
||||
* X * Y == (0)----->-(1)->-----(2)-----(3)
|
||||
*/
|
||||
|
||||
/*
|
||||
* State 0: match 'X'
|
||||
*/
|
||||
if (_strnicmp(lpFileName, lpX, cchX) != 0)
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
* State 1: match 'S' or 'e'
|
||||
*
|
||||
* We use 'e' to transition to state 2
|
||||
*/
|
||||
|
||||
/**
|
||||
* State 2: match Y
|
||||
*/
|
||||
|
||||
if (cchY != 0)
|
||||
{
|
||||
/* TODO: case insensitive character search */
|
||||
lpMatch = strchr(&lpFileName[cchX], *lpY);
|
||||
|
||||
if (!lpMatch)
|
||||
return FALSE;
|
||||
|
||||
if (_strnicmp(lpMatch, lpY, cchY) != 0)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
lpMatch = &lpFileName[cchFileName];
|
||||
}
|
||||
|
||||
/**
|
||||
* State 3: final state
|
||||
*/
|
||||
*ppMatchEnd = &lpMatch[cchY];
|
||||
return TRUE;
|
||||
}
|
||||
else if (*lpWildcard == '?')
|
||||
{
|
||||
/**
|
||||
* X S Y
|
||||
* X ? Y == (0)---(1)---(2)---(3)
|
||||
*/
|
||||
|
||||
/*
|
||||
* State 0: match 'X'
|
||||
*/
|
||||
if (cchFileName < cchX)
|
||||
return FALSE;
|
||||
|
||||
if (_strnicmp(lpFileName, lpX, cchX) != 0)
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
* State 1: match 'S'
|
||||
*/
|
||||
|
||||
/**
|
||||
* State 2: match Y
|
||||
*/
|
||||
|
||||
if (cchY != 0)
|
||||
{
|
||||
/* TODO: case insensitive character search */
|
||||
lpMatch = strchr(&lpFileName[cchX + 1], *lpY);
|
||||
|
||||
if (!lpMatch)
|
||||
return FALSE;
|
||||
|
||||
if (_strnicmp(lpMatch, lpY, cchY) != 0)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((cchX + 1) > cchFileName)
|
||||
return FALSE;
|
||||
|
||||
lpMatch = &lpFileName[cchX + 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* State 3: final state
|
||||
*/
|
||||
*ppMatchEnd = &lpMatch[cchY];
|
||||
return TRUE;
|
||||
}
|
||||
else if (*lpWildcard == '~')
|
||||
{
|
||||
WLog_ERR(TAG, "warning: unimplemented '~' pattern match");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL FilePatternMatchA(LPCSTR lpFileName, LPCSTR lpPattern)
|
||||
{
|
||||
BOOL match = 0;
|
||||
LPCSTR lpTail = nullptr;
|
||||
size_t cchTail = 0;
|
||||
size_t cchPattern = 0;
|
||||
size_t cchFileName = 0;
|
||||
DWORD dwFlags = 0;
|
||||
DWORD dwNextFlags = 0;
|
||||
LPSTR lpWildcard = nullptr;
|
||||
LPSTR lpNextWildcard = nullptr;
|
||||
|
||||
/**
|
||||
* Wild Card Matching
|
||||
*
|
||||
* '*' matches 0 or more characters
|
||||
* '?' matches exactly one character
|
||||
*
|
||||
* '~*' DOS_STAR - matches 0 or more characters until encountering and matching final '.'
|
||||
*
|
||||
* '~?' DOS_QM - matches any single character, or upon encountering a period or end of name
|
||||
* string, advances the expression to the end of the set of contiguous DOS_QMs.
|
||||
*
|
||||
* '~.' DOS_DOT - matches either a '.' or zero characters beyond name string.
|
||||
*/
|
||||
|
||||
if (!lpPattern)
|
||||
return FALSE;
|
||||
|
||||
if (!lpFileName)
|
||||
return FALSE;
|
||||
|
||||
cchPattern = strlen(lpPattern);
|
||||
cchFileName = strlen(lpFileName);
|
||||
|
||||
/**
|
||||
* First and foremost the file system starts off name matching with the expression “*”.
|
||||
* If the expression contains a single wild card character ‘*’ all matches are satisfied
|
||||
* immediately. This is the most common wild card character used in Windows and expression
|
||||
* evaluation is optimized by looking for this character first.
|
||||
*/
|
||||
|
||||
if ((lpPattern[0] == '*') && (cchPattern == 1))
|
||||
return TRUE;
|
||||
|
||||
/**
|
||||
* Subsequently evaluation of the “*X” expression is performed. This is a case where
|
||||
* the expression starts off with a wild card character and contains some non-wild card
|
||||
* characters towards the tail end of the name. This is evaluated by making sure the
|
||||
* expression starts off with the character ‘*’ and does not contain any wildcards in
|
||||
* the latter part of the expression. The tail part of the expression beyond the first
|
||||
* character ‘*’ is matched against the file name at the end uppercasing each character
|
||||
* if necessary during the comparison.
|
||||
*/
|
||||
|
||||
if (lpPattern[0] == '*')
|
||||
{
|
||||
lpTail = &lpPattern[1];
|
||||
cchTail = strlen(lpTail);
|
||||
|
||||
if (!FilePatternFindNextWildcardA(lpTail, &dwFlags))
|
||||
{
|
||||
/* tail contains no wildcards */
|
||||
if (cchFileName < cchTail)
|
||||
return FALSE;
|
||||
|
||||
if (_stricmp(&lpFileName[cchFileName - cchTail], lpTail) == 0)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The remaining expressions are evaluated in a non deterministic
|
||||
* finite order as listed below, where:
|
||||
*
|
||||
* 'S' is any single character
|
||||
* 'S-.' is any single character except the final '.'
|
||||
* 'e' is a null character transition
|
||||
* 'EOF' is the end of the name string
|
||||
*
|
||||
* S
|
||||
* <-----<
|
||||
* X | | e Y
|
||||
* X * Y == (0)----->-(1)->-----(2)-----(3)
|
||||
*
|
||||
*
|
||||
* S-.
|
||||
* <-----<
|
||||
* X | | e Y
|
||||
* X ~* Y == (0)----->-(1)->-----(2)-----(3)
|
||||
*
|
||||
*
|
||||
* X S S Y
|
||||
* X ?? Y == (0)---(1)---(2)---(3)---(4)
|
||||
*
|
||||
*
|
||||
* X S-. S-. Y
|
||||
* X ~?~? == (0)---(1)-----(2)-----(3)---(4)
|
||||
* | |_______|
|
||||
* | ^ |
|
||||
* |_______________|
|
||||
* ^EOF of .^
|
||||
*
|
||||
*/
|
||||
lpWildcard = FilePatternFindNextWildcardA(lpPattern, &dwFlags);
|
||||
|
||||
if (lpWildcard)
|
||||
{
|
||||
LPCSTR lpX = nullptr;
|
||||
LPCSTR lpY = nullptr;
|
||||
size_t cchX = 0;
|
||||
size_t cchY = 0;
|
||||
LPCSTR lpMatchEnd = nullptr;
|
||||
LPCSTR lpSubPattern = nullptr;
|
||||
size_t cchSubPattern = 0;
|
||||
LPCSTR lpSubFileName = nullptr;
|
||||
size_t cchSubFileName = 0;
|
||||
size_t cchWildcard = 0;
|
||||
size_t cchNextWildcard = 0;
|
||||
cchSubPattern = cchPattern;
|
||||
lpSubPattern = lpPattern;
|
||||
cchSubFileName = cchFileName;
|
||||
lpSubFileName = lpFileName;
|
||||
cchWildcard = ((dwFlags & WILDCARD_DOS) ? 2 : 1);
|
||||
lpNextWildcard = FilePatternFindNextWildcardA(&lpWildcard[cchWildcard], &dwNextFlags);
|
||||
|
||||
if (!lpNextWildcard)
|
||||
{
|
||||
lpX = lpSubPattern;
|
||||
cchX = WINPR_ASSERTING_INT_CAST(size_t, (lpWildcard - lpSubPattern));
|
||||
lpY = &lpSubPattern[cchX + cchWildcard];
|
||||
cchY = (cchSubPattern - WINPR_ASSERTING_INT_CAST(size_t, (lpY - lpSubPattern)));
|
||||
match = FilePatternMatchSubExpressionA(lpSubFileName, cchSubFileName, lpX, cchX, lpY,
|
||||
cchY, lpWildcard, &lpMatchEnd);
|
||||
return match;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (lpNextWildcard)
|
||||
{
|
||||
cchSubFileName =
|
||||
cchFileName - WINPR_ASSERTING_INT_CAST(size_t, (lpSubFileName - lpFileName));
|
||||
cchNextWildcard = ((dwNextFlags & WILDCARD_DOS) ? 2 : 1);
|
||||
lpX = lpSubPattern;
|
||||
cchX = WINPR_ASSERTING_INT_CAST(size_t, (lpWildcard - lpSubPattern));
|
||||
lpY = &lpSubPattern[cchX + cchWildcard];
|
||||
cchY =
|
||||
WINPR_ASSERTING_INT_CAST(size_t, (lpNextWildcard - lpWildcard)) - cchWildcard;
|
||||
match = FilePatternMatchSubExpressionA(lpSubFileName, cchSubFileName, lpX, cchX,
|
||||
lpY, cchY, lpWildcard, &lpMatchEnd);
|
||||
|
||||
if (!match)
|
||||
return FALSE;
|
||||
|
||||
lpSubFileName = lpMatchEnd;
|
||||
cchWildcard = cchNextWildcard;
|
||||
lpWildcard = lpNextWildcard;
|
||||
dwFlags = dwNextFlags;
|
||||
lpNextWildcard =
|
||||
FilePatternFindNextWildcardA(&lpWildcard[cchWildcard], &dwNextFlags);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no wildcard characters */
|
||||
if (_stricmp(lpFileName, lpPattern) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
57
third_party/FreeRDP/winpr/libwinpr/file/test/CMakeLists.txt
vendored
Normal file
57
third_party/FreeRDP/winpr/libwinpr/file/test/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
if(NOT WIN32)
|
||||
set(MODULE_NAME "TestFile")
|
||||
set(MODULE_PREFIX "TEST_FILE")
|
||||
|
||||
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(${MODULE_PREFIX}_TESTS
|
||||
TestFileCreateFile.c
|
||||
TestFileDeleteFile.c
|
||||
TestFileReadFile.c
|
||||
TestSetFileAttributes.c
|
||||
TestFileWriteFile.c
|
||||
TestFilePatternMatch.c
|
||||
TestFileFindFirstFile.c
|
||||
TestFileFindFirstFileEx.c
|
||||
TestFileFindNextFile.c
|
||||
TestFileGetStdHandle.c
|
||||
)
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} ${${MODULE_PREFIX}_TESTS})
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
target_link_libraries(${MODULE_NAME} winpr)
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
|
||||
|
||||
if(NOT MSVC)
|
||||
set(TEST_AREA "${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME}Area")
|
||||
else()
|
||||
set(TEST_AREA "${TESTING_OUTPUT_DIRECTORY}/${CMAKE_BUILD_TYPE}/${MODULE_NAME}Area")
|
||||
endif()
|
||||
|
||||
file(MAKE_DIRECTORY "${TEST_AREA}")
|
||||
file(WRITE "${TEST_AREA}/TestFile1" "TestFile1")
|
||||
file(WRITE "${TEST_AREA}/TestFile2" "TestFile2")
|
||||
file(WRITE "${TEST_AREA}/TestFile3" "TestFile3")
|
||||
file(MAKE_DIRECTORY "${TEST_AREA}/TestDirectory1")
|
||||
file(WRITE "${TEST_AREA}/TestDirectory1/TestDirectory1File1" "TestDirectory1File1")
|
||||
file(MAKE_DIRECTORY "${TEST_AREA}/TestDirectory2")
|
||||
file(WRITE "${TEST_AREA}/TestDirectory2/TestDirectory2File1" "TestDirectory2File1")
|
||||
file(WRITE "${TEST_AREA}/TestDirectory2/TestDirectory2File2" "TestDirectory2File2")
|
||||
file(MAKE_DIRECTORY "${TEST_AREA}/TestDirectory3")
|
||||
file(WRITE "${TEST_AREA}/TestDirectory3/TestDirectory3File1" "TestDirectory3File1")
|
||||
file(WRITE "${TEST_AREA}/TestDirectory3/TestDirectory3File2" "TestDirectory3File2")
|
||||
file(WRITE "${TEST_AREA}/TestDirectory3/TestDirectory3File3" "TestDirectory3File3")
|
||||
|
||||
foreach(test ${${MODULE_PREFIX}_TESTS})
|
||||
get_filename_component(TestName ${test} NAME_WE)
|
||||
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName} ${TEST_AREA})
|
||||
endforeach()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test")
|
||||
|
||||
endif()
|
||||
94
third_party/FreeRDP/winpr/libwinpr/file/test/TestFileCreateFile.c
vendored
Normal file
94
third_party/FreeRDP/winpr/libwinpr/file/test/TestFileCreateFile.c
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/handle.h>
|
||||
#include <winpr/windows.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
int TestFileCreateFile(int argc, char* argv[])
|
||||
{
|
||||
HANDLE handle = nullptr;
|
||||
HRESULT hr = 0;
|
||||
DWORD written = 0;
|
||||
const char buffer[] = "Some random text\r\njust want it done.";
|
||||
char cmp[sizeof(buffer)];
|
||||
char sname[8192];
|
||||
LPSTR name = nullptr;
|
||||
int rc = 0;
|
||||
SYSTEMTIME systemTime;
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
GetSystemTime(&systemTime);
|
||||
(void)sprintf_s(sname, sizeof(sname),
|
||||
"CreateFile-%04" PRIu16 "%02" PRIu16 "%02" PRIu16 "%02" PRIu16 "%02" PRIu16
|
||||
"%02" PRIu16 "%04" PRIu16,
|
||||
systemTime.wYear, systemTime.wMonth, systemTime.wDay, systemTime.wHour,
|
||||
systemTime.wMinute, systemTime.wSecond, systemTime.wMilliseconds);
|
||||
name = GetKnownSubPath(KNOWN_PATH_TEMP, sname);
|
||||
|
||||
if (!name)
|
||||
return -1;
|
||||
|
||||
/* On windows we would need '\\' or '/' as separator.
|
||||
* Single '\' do not work. */
|
||||
hr = PathCchConvertStyleA(name, strlen(name), PATH_STYLE_UNIX);
|
||||
|
||||
if (FAILED(hr))
|
||||
rc = -1;
|
||||
|
||||
handle = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_NEW,
|
||||
FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
free(name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!winpr_PathFileExists(name))
|
||||
rc = -1;
|
||||
|
||||
if (!WriteFile(handle, buffer, sizeof(buffer), &written, nullptr))
|
||||
rc = -1;
|
||||
|
||||
if (written != sizeof(buffer))
|
||||
rc = -1;
|
||||
|
||||
written = SetFilePointer(handle, 5, nullptr, FILE_BEGIN);
|
||||
|
||||
if (written != 5)
|
||||
rc = -1;
|
||||
|
||||
written = SetFilePointer(handle, 0, nullptr, FILE_CURRENT);
|
||||
|
||||
if (written != 5)
|
||||
rc = -1;
|
||||
|
||||
written = SetFilePointer(handle, -5, nullptr, FILE_CURRENT);
|
||||
|
||||
if (written != 0)
|
||||
rc = -1;
|
||||
|
||||
if (!ReadFile(handle, cmp, sizeof(cmp), &written, nullptr))
|
||||
rc = -1;
|
||||
|
||||
if (written != sizeof(cmp))
|
||||
rc = -1;
|
||||
|
||||
if (memcmp(buffer, cmp, sizeof(buffer)) != 0)
|
||||
rc = -1;
|
||||
|
||||
if (!CloseHandle(handle))
|
||||
rc = -1;
|
||||
|
||||
if (!winpr_DeleteFile(name))
|
||||
rc = -1;
|
||||
|
||||
if (winpr_PathFileExists(name))
|
||||
rc = -1;
|
||||
|
||||
free(name);
|
||||
return rc;
|
||||
}
|
||||
67
third_party/FreeRDP/winpr/libwinpr/file/test/TestFileDeleteFile.c
vendored
Normal file
67
third_party/FreeRDP/winpr/libwinpr/file/test/TestFileDeleteFile.c
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/windows.h>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
static int secure_mkstemp(char* tmpname)
|
||||
{
|
||||
#if !defined(_WIN32)
|
||||
const mode_t mask = umask(S_IRWXU);
|
||||
#endif
|
||||
int fd = mkstemp(tmpname);
|
||||
#if !defined(_WIN32)
|
||||
(void)umask(mask);
|
||||
#endif
|
||||
return fd;
|
||||
}
|
||||
|
||||
int TestFileDeleteFile(int argc, char* argv[])
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
int fd = 0;
|
||||
char validA[] = "/tmp/valid-test-file-XXXXXX";
|
||||
char validW[] = "/tmp/valid-test-file-XXXXXX";
|
||||
WCHAR* validWW = nullptr;
|
||||
const char invalidA[] = "/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
WCHAR invalidW[sizeof(invalidA)] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
(void)ConvertUtf8NToWChar(invalidA, ARRAYSIZE(invalidA), invalidW, ARRAYSIZE(invalidW));
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
rc = winpr_DeleteFile(invalidA);
|
||||
if (rc)
|
||||
return -1;
|
||||
|
||||
rc = DeleteFileW(invalidW);
|
||||
if (rc)
|
||||
return -1;
|
||||
|
||||
fd = secure_mkstemp(validA);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
rc = winpr_DeleteFile(validA);
|
||||
if (!rc)
|
||||
return -1;
|
||||
|
||||
fd = secure_mkstemp(validW);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
validWW = ConvertUtf8NToWCharAlloc(validW, ARRAYSIZE(validW), nullptr);
|
||||
if (validWW)
|
||||
rc = DeleteFileW(validWW);
|
||||
free(validWW);
|
||||
if (!rc)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
360
third_party/FreeRDP/winpr/libwinpr/file/test/TestFileFindFirstFile.c
vendored
Normal file
360
third_party/FreeRDP/winpr/libwinpr/file/test/TestFileFindFirstFile.c
vendored
Normal file
@@ -0,0 +1,360 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/handle.h>
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/collections.h>
|
||||
#include <winpr/windows.h>
|
||||
|
||||
static const CHAR testFile1A[] = "TestFile1A";
|
||||
|
||||
static BOOL create_fileA(const char* FilePath)
|
||||
{
|
||||
HANDLE hdl = CreateFileA(FilePath, GENERIC_ALL, 0, nullptr, CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (hdl == INVALID_HANDLE_VALUE)
|
||||
return FALSE;
|
||||
(void)CloseHandle(hdl);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL create_fileW(const WCHAR* FilePath)
|
||||
{
|
||||
HANDLE hdl = CreateFileW(FilePath, GENERIC_ALL, 0, nullptr, CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (hdl == INVALID_HANDLE_VALUE)
|
||||
return FALSE;
|
||||
(void)CloseHandle(hdl);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL create_layout_files(size_t level, const char* BasePath, wArrayList* files)
|
||||
{
|
||||
for (size_t x = 0; x < 10; x++)
|
||||
{
|
||||
CHAR FilePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
|
||||
strncpy(FilePath, BasePath, ARRAYSIZE(FilePath));
|
||||
|
||||
CHAR name[64] = WINPR_C_ARRAY_INIT;
|
||||
(void)_snprintf(name, ARRAYSIZE(name), "%zd-TestFile%zd", level, x);
|
||||
NativePathCchAppendA(FilePath, PATHCCH_MAX_CCH, name);
|
||||
|
||||
if (create_fileA(FilePath))
|
||||
ArrayList_Append(files, FilePath);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL create_layout_directories(size_t level, size_t max_level, const char* BasePath,
|
||||
wArrayList* files)
|
||||
{
|
||||
if (level >= max_level)
|
||||
return TRUE;
|
||||
|
||||
CHAR FilePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
|
||||
strncpy(FilePath, BasePath, ARRAYSIZE(FilePath));
|
||||
PathCchConvertStyleA(FilePath, ARRAYSIZE(FilePath), PATH_STYLE_NATIVE);
|
||||
if (!winpr_PathMakePath(FilePath, nullptr))
|
||||
return FALSE;
|
||||
ArrayList_Append(files, FilePath);
|
||||
|
||||
if (!create_layout_files(level + 1, BasePath, files))
|
||||
return FALSE;
|
||||
|
||||
for (size_t x = 0; x < 10; x++)
|
||||
{
|
||||
CHAR CurFilePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
|
||||
strncpy(CurFilePath, FilePath, ARRAYSIZE(CurFilePath));
|
||||
|
||||
PathCchConvertStyleA(CurFilePath, ARRAYSIZE(CurFilePath), PATH_STYLE_NATIVE);
|
||||
|
||||
CHAR name[64] = WINPR_C_ARRAY_INIT;
|
||||
(void)_snprintf(name, ARRAYSIZE(name), "%zd-TestPath%zd", level, x);
|
||||
NativePathCchAppendA(CurFilePath, PATHCCH_MAX_CCH, name);
|
||||
|
||||
if (!create_layout_directories(level + 1, max_level, CurFilePath, files))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL create_layout(const char* BasePath, wArrayList* files)
|
||||
{
|
||||
CHAR BasePathNative[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
|
||||
memcpy(BasePathNative, BasePath, sizeof(BasePathNative));
|
||||
PathCchConvertStyleA(BasePathNative, ARRAYSIZE(BasePathNative), PATH_STYLE_NATIVE);
|
||||
|
||||
return create_layout_directories(0, 3, BasePathNative, files);
|
||||
}
|
||||
|
||||
static void cleanup_layout(const char* BasePath)
|
||||
{
|
||||
winpr_RemoveDirectory_RecursiveA(BasePath);
|
||||
}
|
||||
|
||||
static BOOL find_first_file_success(const char* FilePath)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
WIN32_FIND_DATAA FindData = WINPR_C_ARRAY_INIT;
|
||||
HANDLE hFind = FindFirstFileA(FilePath, &FindData);
|
||||
if (hFind == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
printf("FindFirstFile failure: %s (INVALID_HANDLE_VALUE -1)\n", FilePath);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
printf("FindFirstFile: %s\n", FindData.cFileName);
|
||||
|
||||
if (strcmp(FindData.cFileName, testFile1A) != 0)
|
||||
{
|
||||
printf("FindFirstFile failure: Expected: %s, Actual: %s\n", testFile1A, FindData.cFileName);
|
||||
goto fail;
|
||||
}
|
||||
rc = TRUE;
|
||||
fail:
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
FindClose(hFind);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL list_directory_dot(const char* BasePath, wArrayList* files)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
CHAR BasePathDot[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
|
||||
memcpy(BasePathDot, BasePath, ARRAYSIZE(BasePathDot));
|
||||
PathCchConvertStyleA(BasePathDot, ARRAYSIZE(BasePathDot), PATH_STYLE_NATIVE);
|
||||
NativePathCchAppendA(BasePathDot, PATHCCH_MAX_CCH, ".");
|
||||
WIN32_FIND_DATAA FindData = WINPR_C_ARRAY_INIT;
|
||||
HANDLE hFind = FindFirstFileA(BasePathDot, &FindData);
|
||||
if (hFind == INVALID_HANDLE_VALUE)
|
||||
return FALSE;
|
||||
size_t count = 0;
|
||||
do
|
||||
{
|
||||
count++;
|
||||
if (strcmp(FindData.cFileName, ".") != 0)
|
||||
goto fail;
|
||||
} while (FindNextFile(hFind, &FindData));
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
FindClose(hFind);
|
||||
|
||||
if (count != 1)
|
||||
return FALSE;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL list_directory_star(const char* BasePath, wArrayList* files)
|
||||
{
|
||||
CHAR BasePathDot[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
|
||||
memcpy(BasePathDot, BasePath, ARRAYSIZE(BasePathDot));
|
||||
PathCchConvertStyleA(BasePathDot, ARRAYSIZE(BasePathDot), PATH_STYLE_NATIVE);
|
||||
NativePathCchAppendA(BasePathDot, PATHCCH_MAX_CCH, "*");
|
||||
WIN32_FIND_DATAA FindData = WINPR_C_ARRAY_INIT;
|
||||
HANDLE hFind = FindFirstFileA(BasePathDot, &FindData);
|
||||
if (hFind == INVALID_HANDLE_VALUE)
|
||||
return FALSE;
|
||||
size_t count = 0;
|
||||
size_t dotcount = 0;
|
||||
size_t dotdotcount = 0;
|
||||
do
|
||||
{
|
||||
if (strcmp(FindData.cFileName, ".") == 0)
|
||||
dotcount++;
|
||||
else if (strcmp(FindData.cFileName, "..") == 0)
|
||||
dotdotcount++;
|
||||
else
|
||||
count++;
|
||||
} while (FindNextFile(hFind, &FindData));
|
||||
FindClose(hFind);
|
||||
|
||||
const char sep = PathGetSeparatorA(PATH_STYLE_NATIVE);
|
||||
size_t fcount = 0;
|
||||
const size_t baselen = strlen(BasePath);
|
||||
const size_t total = ArrayList_Count(files);
|
||||
for (size_t x = 0; x < total; x++)
|
||||
{
|
||||
const char* path = ArrayList_GetItem(files, x);
|
||||
const size_t pathlen = strlen(path);
|
||||
if (pathlen < baselen)
|
||||
continue;
|
||||
const char* skip = &path[baselen];
|
||||
if (*skip == sep)
|
||||
skip++;
|
||||
const char* end = strrchr(skip, sep);
|
||||
if (end)
|
||||
continue;
|
||||
fcount++;
|
||||
}
|
||||
|
||||
return (fcount == count);
|
||||
}
|
||||
|
||||
static BOOL find_first_file_fail(const char* FilePath)
|
||||
{
|
||||
WIN32_FIND_DATAA FindData = WINPR_C_ARRAY_INIT;
|
||||
HANDLE hFind = FindFirstFileA(FilePath, &FindData);
|
||||
if (hFind == INVALID_HANDLE_VALUE)
|
||||
return TRUE;
|
||||
|
||||
FindClose(hFind);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int TestFileFindFirstFileA(const char* str)
|
||||
{
|
||||
int rc = -1;
|
||||
|
||||
printf("[%s] basepath: '%s'\n", __func__, str);
|
||||
if (!str)
|
||||
return -1;
|
||||
|
||||
CHAR BasePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
strncpy(BasePath, str, ARRAYSIZE(BasePath));
|
||||
|
||||
const size_t length = strnlen(BasePath, PATHCCH_MAX_CCH - 1);
|
||||
|
||||
CHAR FilePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
|
||||
CopyMemory(FilePath, BasePath, length * sizeof(CHAR));
|
||||
|
||||
PathCchConvertStyleA(BasePath, length, PATH_STYLE_WINDOWS);
|
||||
|
||||
wArrayList* files = ArrayList_New(FALSE);
|
||||
if (!files)
|
||||
return -3;
|
||||
wObject* obj = ArrayList_Object(files);
|
||||
obj->fnObjectFree = winpr_ObjectStringFree;
|
||||
obj->fnObjectNew = winpr_ObjectStringClone;
|
||||
|
||||
if (!create_layout(BasePath, files))
|
||||
goto fail;
|
||||
|
||||
NativePathCchAppendA(FilePath, PATHCCH_MAX_CCH, testFile1A);
|
||||
|
||||
printf("Finding file: %s\n", FilePath);
|
||||
|
||||
if (!find_first_file_fail(FilePath))
|
||||
goto fail;
|
||||
|
||||
if (!create_fileA(FilePath))
|
||||
goto fail;
|
||||
|
||||
if (!find_first_file_success(FilePath))
|
||||
goto fail;
|
||||
|
||||
CHAR BasePathInvalid[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
|
||||
memcpy(BasePathInvalid, BasePath, ARRAYSIZE(BasePathInvalid));
|
||||
PathCchAddBackslashA(BasePathInvalid, PATHCCH_MAX_CCH);
|
||||
|
||||
if (!find_first_file_fail(BasePathInvalid))
|
||||
goto fail;
|
||||
|
||||
if (!list_directory_dot(BasePath, files))
|
||||
goto fail;
|
||||
|
||||
if (!list_directory_star(BasePath, files))
|
||||
goto fail;
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
winpr_DeleteFile(FilePath);
|
||||
cleanup_layout(BasePath);
|
||||
ArrayList_Free(files);
|
||||
return rc;
|
||||
}
|
||||
|
||||
WINPR_ATTR_FORMAT_ARG(1, 0)
|
||||
static int printf1W(const char* WINPR_FORMAT_ARG fmt, const WCHAR* arg1)
|
||||
{
|
||||
char* var1 = ConvertWCharToUtf8Alloc(arg1, nullptr);
|
||||
const int rc = printf(fmt, var1);
|
||||
free(var1);
|
||||
return rc;
|
||||
}
|
||||
|
||||
WINPR_ATTR_FORMAT_ARG(1, 0)
|
||||
static int printf2W(const char* WINPR_FORMAT_ARG fmt, const WCHAR* arg1, const WCHAR* arg2)
|
||||
{
|
||||
char* var1 = ConvertWCharToUtf8Alloc(arg1, nullptr);
|
||||
char* var2 = ConvertWCharToUtf8Alloc(arg2, nullptr);
|
||||
const int rc = printf(fmt, var1, var2);
|
||||
free(var1);
|
||||
free(var2);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int TestFileFindFirstFileW(const char* str)
|
||||
{
|
||||
WCHAR buffer[32] = WINPR_C_ARRAY_INIT;
|
||||
const WCHAR* testFile1W = InitializeConstWCharFromUtf8("TestFile1W", buffer, ARRAYSIZE(buffer));
|
||||
int rc = -1;
|
||||
if (!str)
|
||||
return -1;
|
||||
|
||||
WCHAR BasePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
printf("[%s] basepath: '%s'\n", __func__, str);
|
||||
(void)ConvertUtf8ToWChar(str, BasePath, ARRAYSIZE(BasePath));
|
||||
|
||||
const size_t length = _wcsnlen(BasePath, PATHCCH_MAX_CCH - 1);
|
||||
|
||||
WCHAR FilePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
|
||||
CopyMemory(FilePath, BasePath, length * sizeof(WCHAR));
|
||||
|
||||
PathCchConvertStyleW(BasePath, length, PATH_STYLE_WINDOWS);
|
||||
NativePathCchAppendW(FilePath, PATHCCH_MAX_CCH, testFile1W);
|
||||
|
||||
HANDLE hFind = INVALID_HANDLE_VALUE;
|
||||
if (!create_fileW(FilePath))
|
||||
goto fail;
|
||||
|
||||
printf1W("Finding file: %s\n", FilePath);
|
||||
|
||||
WIN32_FIND_DATAW FindData = WINPR_C_ARRAY_INIT;
|
||||
hFind = FindFirstFileW(FilePath, &FindData);
|
||||
|
||||
if (hFind == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
printf1W("FindFirstFile failure: %s (INVALID_HANDLE_VALUE -1)\n", FilePath);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
printf1W("FindFirstFile: %s\n", FindData.cFileName);
|
||||
|
||||
if (_wcscmp(FindData.cFileName, testFile1W) != 0)
|
||||
{
|
||||
printf2W("FindFirstFile failure: Expected: %s, Actual: %s\n", testFile1W,
|
||||
FindData.cFileName);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
DeleteFileW(FilePath);
|
||||
FindClose(hFind);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int TestFileFindFirstFile(int argc, char* argv[])
|
||||
{
|
||||
char* str = GetKnownSubPath(KNOWN_PATH_TEMP, "TestFileFindFirstFile");
|
||||
if (!str)
|
||||
return -23;
|
||||
|
||||
cleanup_layout(str);
|
||||
|
||||
int rc1 = -1;
|
||||
int rc2 = -1;
|
||||
if (winpr_PathMakePath(str, nullptr))
|
||||
{
|
||||
rc1 = TestFileFindFirstFileA(str);
|
||||
rc2 = TestFileFindFirstFileW(str);
|
||||
winpr_RemoveDirectory(str);
|
||||
}
|
||||
free(str);
|
||||
return rc1 + rc2;
|
||||
}
|
||||
10
third_party/FreeRDP/winpr/libwinpr/file/test/TestFileFindFirstFileEx.c
vendored
Normal file
10
third_party/FreeRDP/winpr/libwinpr/file/test/TestFileFindFirstFileEx.c
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/windows.h>
|
||||
|
||||
int TestFileFindFirstFileEx(int argc, char* argv[])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
99
third_party/FreeRDP/winpr/libwinpr/file/test/TestFileFindNextFile.c
vendored
Normal file
99
third_party/FreeRDP/winpr/libwinpr/file/test/TestFileFindNextFile.c
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/windows.h>
|
||||
|
||||
static TCHAR testDirectory2File1[] = _T("TestDirectory2File1");
|
||||
static TCHAR testDirectory2File2[] = _T("TestDirectory2File2");
|
||||
|
||||
int TestFileFindNextFile(int argc, char* argv[])
|
||||
{
|
||||
char* str = nullptr;
|
||||
size_t length = 0;
|
||||
BOOL status = 0;
|
||||
HANDLE hFind = nullptr;
|
||||
LPTSTR BasePath = nullptr;
|
||||
WIN32_FIND_DATA FindData;
|
||||
TCHAR FilePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
|
||||
WINPR_UNUSED(argc);
|
||||
str = argv[1];
|
||||
#ifdef UNICODE
|
||||
BasePath = ConvertUtf8ToWChar(str, &length);
|
||||
|
||||
if (!BasePath)
|
||||
{
|
||||
_tprintf(_T("Unable to allocate memory"));
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
BasePath = _strdup(str);
|
||||
|
||||
if (!BasePath)
|
||||
{
|
||||
printf("Unable to allocate memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
length = strlen(BasePath);
|
||||
#endif
|
||||
/* Simple filter matching all files inside current directory */
|
||||
CopyMemory(FilePath, BasePath, length * sizeof(TCHAR));
|
||||
FilePath[length] = 0;
|
||||
PathCchConvertStyle(BasePath, length, PATH_STYLE_WINDOWS);
|
||||
NativePathCchAppend(FilePath, PATHCCH_MAX_CCH, _T("TestDirectory2"));
|
||||
NativePathCchAppend(FilePath, PATHCCH_MAX_CCH, _T("TestDirectory2File*"));
|
||||
free(BasePath);
|
||||
_tprintf(_T("Finding file: %s\n"), FilePath);
|
||||
hFind = FindFirstFile(FilePath, &FindData);
|
||||
|
||||
if (hFind == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
_tprintf(_T("FindFirstFile failure: %s\n"), FilePath);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_tprintf(_T("FindFirstFile: %s"), FindData.cFileName);
|
||||
|
||||
/**
|
||||
* The current implementation does not enforce a particular order
|
||||
*/
|
||||
|
||||
if ((_tcsncmp(FindData.cFileName, testDirectory2File1, ARRAYSIZE(testDirectory2File1)) != 0) &&
|
||||
(_tcsncmp(FindData.cFileName, testDirectory2File2, ARRAYSIZE(testDirectory2File2)) != 0))
|
||||
{
|
||||
_tprintf(_T("FindFirstFile failure: Expected: %s, Actual: %s\n"), testDirectory2File1,
|
||||
FindData.cFileName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = FindNextFile(hFind, &FindData);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
_tprintf(_T("FindNextFile failure: Expected: TRUE, Actual: %") _T(PRId32) _T("\n"), status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((_tcsncmp(FindData.cFileName, testDirectory2File1, ARRAYSIZE(testDirectory2File1)) != 0) &&
|
||||
(_tcsncmp(FindData.cFileName, testDirectory2File2, ARRAYSIZE(testDirectory2File2)) != 0))
|
||||
{
|
||||
_tprintf(_T("FindNextFile failure: Expected: %s, Actual: %s\n"), testDirectory2File2,
|
||||
FindData.cFileName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = FindNextFile(hFind, &FindData);
|
||||
|
||||
if (status)
|
||||
{
|
||||
_tprintf(_T("FindNextFile failure: Expected: FALSE, Actual: %") _T(PRId32) _T("\n"),
|
||||
status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
FindClose(hFind);
|
||||
return 0;
|
||||
}
|
||||
49
third_party/FreeRDP/winpr/libwinpr/file/test/TestFileGetStdHandle.c
vendored
Normal file
49
third_party/FreeRDP/winpr/libwinpr/file/test/TestFileGetStdHandle.c
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* File Functions
|
||||
*
|
||||
* Copyright 2015 Thincast Technologies GmbH
|
||||
* Copyright 2015 Bernhard Miklautz <bernhard.miklautz@thincast.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/handle.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int TestFileGetStdHandle(int argc, char* argv[])
|
||||
{
|
||||
HANDLE so = nullptr;
|
||||
const char buf[] = "happy happy";
|
||||
DWORD bytesWritten = 0;
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
so = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (so == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
(void)fprintf(stderr, "GetStdHandle failed ;(\n");
|
||||
return -1;
|
||||
}
|
||||
WriteFile(so, buf, strnlen(buf, sizeof(buf)), &bytesWritten, nullptr);
|
||||
if (bytesWritten != strnlen(buf, sizeof(buf)))
|
||||
{
|
||||
(void)fprintf(stderr, "write failed\n");
|
||||
return -1;
|
||||
}
|
||||
(void)CloseHandle(so);
|
||||
|
||||
return 0;
|
||||
}
|
||||
182
third_party/FreeRDP/winpr/libwinpr/file/test/TestFilePatternMatch.c
vendored
Normal file
182
third_party/FreeRDP/winpr/libwinpr/file/test/TestFilePatternMatch.c
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/windows.h>
|
||||
|
||||
int TestFilePatternMatch(int argc, char* argv[])
|
||||
{
|
||||
/* '*' expression */
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
if (!FilePatternMatchA("document.txt", "*"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "document.txt", "*");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* '*X' expression */
|
||||
|
||||
if (!FilePatternMatchA("document.txt", "*.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "document.txt", "*.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (FilePatternMatchA("document.docx", "*.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "document.docx", "*.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (FilePatternMatchA("document.txt.bak", "*.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "document.txt.bak", "*.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (FilePatternMatchA("bak", "*.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "bak", "*.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 'X*' expression */
|
||||
|
||||
if (!FilePatternMatchA("document.txt", "document.*"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "document.txt", "document.*");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 'X?' expression */
|
||||
|
||||
if (!FilePatternMatchA("document.docx", "document.doc?"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "document.docx",
|
||||
"document.doc?");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (FilePatternMatchA("document.doc", "document.doc?"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "document.doc",
|
||||
"document.doc?");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* no wildcards expression */
|
||||
|
||||
if (!FilePatternMatchA("document.txt", "document.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "document.txt",
|
||||
"document.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 'X * Y' expression */
|
||||
|
||||
if (!FilePatternMatchA("X123Y.txt", "X*Y.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X123Y.txt", "X*Y.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!FilePatternMatchA("XY.txt", "X*Y.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XY.txt", "X*Y.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (FilePatternMatchA("XZ.txt", "X*Y.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XZ.txt", "X*Y.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (FilePatternMatchA("X123Z.txt", "X*Y.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X123Z.txt", "X*Y.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 'X * Y * Z' expression */
|
||||
|
||||
if (!FilePatternMatchA("X123Y456Z.txt", "X*Y*Z.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X123Y456Z.txt", "X*Y*Z.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!FilePatternMatchA("XYZ.txt", "X*Y*Z.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XYZ.txt", "X*Y*Z.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!FilePatternMatchA("X123Y456W.txt", "X*Y*Z.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X123Y456W.txt", "X*Y*Z.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!FilePatternMatchA("XYW.txt", "X*Y*Z.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XYW.txt", "X*Y*Z.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 'X ? Y' expression */
|
||||
|
||||
if (!FilePatternMatchA("X1Y.txt", "X?Y.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X1Y.txt", "X?Y.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (FilePatternMatchA("XY.txt", "X?Y.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XY.txt", "X?Y.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (FilePatternMatchA("XZ.txt", "X?Y.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XZ.txt", "X?Y.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (FilePatternMatchA("X123Z.txt", "X?Y.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X123Z.txt", "X?Y.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 'X ? Y ? Z' expression */
|
||||
|
||||
if (!FilePatternMatchA("X123Y456Z.txt", "X?Y?Z.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X123Y456Z.txt", "X?Y?Z.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (FilePatternMatchA("XYZ.txt", "X?Y?Z.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XYZ.txt", "X?Y?Z.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!FilePatternMatchA("X123Y456W.txt", "X?Y?Z.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "X123Y456W.txt", "X?Y?Z.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (FilePatternMatchA("XYW.txt", "X?Y?Z.txt"))
|
||||
{
|
||||
printf("FilePatternMatchA error: FileName: %s Pattern: %s\n", "XYW.txt", "X?Y?Z.txt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
10
third_party/FreeRDP/winpr/libwinpr/file/test/TestFileReadFile.c
vendored
Normal file
10
third_party/FreeRDP/winpr/libwinpr/file/test/TestFileReadFile.c
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/windows.h>
|
||||
|
||||
int TestFileReadFile(int argc, char* argv[])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
128
third_party/FreeRDP/winpr/libwinpr/file/test/TestFileWriteFile.c
vendored
Normal file
128
third_party/FreeRDP/winpr/libwinpr/file/test/TestFileWriteFile.c
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/windows.h>
|
||||
|
||||
static const char* get_dir(char* filename, size_t len)
|
||||
{
|
||||
#if defined(WIN32)
|
||||
if ((len == 0) || (strnlen_s(filename, len) == len))
|
||||
return nullptr;
|
||||
char* ptr = strrchr(filename, '\\');
|
||||
#else
|
||||
if ((len == 0) || (strnlen(filename, len) == len))
|
||||
return nullptr;
|
||||
char* ptr = strrchr(filename, '/');
|
||||
#endif
|
||||
if (!ptr)
|
||||
return nullptr;
|
||||
*ptr = '\0';
|
||||
return filename;
|
||||
}
|
||||
|
||||
static BOOL get_tmp(char* path, size_t len)
|
||||
{
|
||||
#if defined(WIN32)
|
||||
const char template[] = "tmpdir.XXXXXX";
|
||||
strncmp(path, template, strnlen_s(template, len) + 1);
|
||||
if (!mktemp_s(path))
|
||||
return FALSE;
|
||||
return winpr_str_append("testfile", path, len, "\\");
|
||||
#else
|
||||
const char template[] = "/tmp/tmpdir.XXXXXX";
|
||||
if (!strncpy(path, template, strnlen(template, len) + 1))
|
||||
return FALSE;
|
||||
if (!mkdtemp(path))
|
||||
return FALSE;
|
||||
return winpr_str_append("testfile", path, len, "/");
|
||||
#endif
|
||||
}
|
||||
|
||||
static BOOL test_write(const char* filename, const char* data, size_t datalen)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
|
||||
WINPR_ASSERT(filename);
|
||||
WINPR_ASSERT(data);
|
||||
WINPR_ASSERT(datalen > 0);
|
||||
|
||||
HANDLE hdl = CreateFileA(filename, GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL,
|
||||
nullptr);
|
||||
if (!hdl || (hdl == INVALID_HANDLE_VALUE))
|
||||
goto fail;
|
||||
|
||||
DWORD written = 0;
|
||||
if (!WriteFile(hdl, data, datalen, &written, nullptr))
|
||||
goto fail;
|
||||
if (written != datalen)
|
||||
goto fail;
|
||||
|
||||
if (!FlushFileBuffers(hdl))
|
||||
goto fail;
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
CloseHandle(hdl);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL test_read(const char* filename, const char* data, size_t datalen)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
|
||||
WINPR_ASSERT(filename);
|
||||
WINPR_ASSERT(data);
|
||||
WINPR_ASSERT(datalen > 0);
|
||||
|
||||
char* cmp = calloc(datalen + 1, sizeof(char));
|
||||
HANDLE hdl = CreateFileA(filename, GENERIC_READ, 0, nullptr, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (!hdl || (hdl == INVALID_HANDLE_VALUE) || !cmp)
|
||||
goto fail;
|
||||
|
||||
DWORD read = 0;
|
||||
if (!ReadFile(hdl, cmp, datalen, &read, nullptr))
|
||||
goto fail;
|
||||
if (read != datalen)
|
||||
goto fail;
|
||||
if (memcmp(data, cmp, datalen) != 0)
|
||||
goto fail;
|
||||
if (FlushFileBuffers(hdl))
|
||||
goto fail;
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
free(cmp);
|
||||
CloseHandle(hdl);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int TestFileWriteFile(int argc, char* argv[])
|
||||
{
|
||||
const char data[] = "sometesttext\nanother line\r\ngogogo\r\tfoo\t\r\n\r";
|
||||
char filename[MAX_PATH] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
int rc = -1;
|
||||
if (!get_tmp(filename, sizeof(filename)))
|
||||
goto fail;
|
||||
|
||||
if (!test_write(filename, data, sizeof(data)))
|
||||
goto fail;
|
||||
|
||||
if (!test_read(filename, data, sizeof(data)))
|
||||
goto fail;
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
if (!DeleteFile(filename))
|
||||
rc = -2;
|
||||
|
||||
const char* d = get_dir(filename, sizeof(filename));
|
||||
if (d)
|
||||
{
|
||||
if (!RemoveDirectory(d))
|
||||
rc = -3;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
152
third_party/FreeRDP/winpr/libwinpr/file/test/TestSetFileAttributes.c
vendored
Normal file
152
third_party/FreeRDP/winpr/libwinpr/file/test/TestSetFileAttributes.c
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/handle.h>
|
||||
#include <winpr/windows.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
static const DWORD allflags[] = {
|
||||
0,
|
||||
FILE_ATTRIBUTE_READONLY,
|
||||
FILE_ATTRIBUTE_HIDDEN,
|
||||
FILE_ATTRIBUTE_SYSTEM,
|
||||
FILE_ATTRIBUTE_DIRECTORY,
|
||||
FILE_ATTRIBUTE_ARCHIVE,
|
||||
FILE_ATTRIBUTE_DEVICE,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
FILE_ATTRIBUTE_TEMPORARY,
|
||||
FILE_ATTRIBUTE_SPARSE_FILE,
|
||||
FILE_ATTRIBUTE_REPARSE_POINT,
|
||||
FILE_ATTRIBUTE_COMPRESSED,
|
||||
FILE_ATTRIBUTE_OFFLINE,
|
||||
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
|
||||
FILE_ATTRIBUTE_ENCRYPTED,
|
||||
FILE_ATTRIBUTE_VIRTUAL,
|
||||
FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM,
|
||||
FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_DEVICE |
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_SPARSE_FILE | FILE_ATTRIBUTE_REPARSE_POINT |
|
||||
FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_OFFLINE,
|
||||
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_VIRTUAL
|
||||
};
|
||||
|
||||
static BOOL test_SetFileAttributesA(void)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
HANDLE handle = nullptr;
|
||||
const DWORD flags[] = { 0, FILE_ATTRIBUTE_READONLY };
|
||||
char* name = GetKnownSubPath(KNOWN_PATH_TEMP, "afsklhjwe4oq5iu432oijrlkejadlkhjaklhfdkahfd");
|
||||
if (!name)
|
||||
goto fail;
|
||||
|
||||
for (size_t x = 0; x < ARRAYSIZE(allflags); x++)
|
||||
{
|
||||
const DWORD flag = allflags[x];
|
||||
const BOOL brc = SetFileAttributesA(nullptr, flag);
|
||||
if (brc)
|
||||
goto fail;
|
||||
|
||||
const BOOL crc = SetFileAttributesA(name, flag);
|
||||
if (crc)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
handle = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_NEW,
|
||||
FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
goto fail;
|
||||
(void)CloseHandle(handle);
|
||||
|
||||
for (size_t x = 0; x < ARRAYSIZE(flags); x++)
|
||||
{
|
||||
DWORD attr = 0;
|
||||
const DWORD flag = flags[x];
|
||||
const BOOL brc = SetFileAttributesA(name, flag);
|
||||
if (!brc)
|
||||
goto fail;
|
||||
|
||||
attr = GetFileAttributesA(name);
|
||||
if (flag != 0)
|
||||
{
|
||||
if ((attr & flag) == 0)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
|
||||
fail:
|
||||
winpr_DeleteFile(name);
|
||||
free(name);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL test_SetFileAttributesW(void)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
WCHAR* name = nullptr;
|
||||
HANDLE handle = nullptr;
|
||||
const DWORD flags[] = { 0, FILE_ATTRIBUTE_READONLY };
|
||||
char* base = GetKnownSubPath(KNOWN_PATH_TEMP, "afsklhjwe4oq5iu432oijrlkejadlkhjaklhfdkahfd");
|
||||
if (!base)
|
||||
goto fail;
|
||||
|
||||
name = ConvertUtf8ToWCharAlloc(base, nullptr);
|
||||
if (!name)
|
||||
goto fail;
|
||||
|
||||
for (size_t x = 0; x < ARRAYSIZE(allflags); x++)
|
||||
{
|
||||
const DWORD flag = allflags[x];
|
||||
const BOOL brc = SetFileAttributesW(nullptr, flag);
|
||||
if (brc)
|
||||
goto fail;
|
||||
|
||||
const BOOL crc = SetFileAttributesW(name, flag);
|
||||
if (crc)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
handle = CreateFileW(name, GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_NEW,
|
||||
FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
goto fail;
|
||||
(void)CloseHandle(handle);
|
||||
|
||||
for (size_t x = 0; x < ARRAYSIZE(flags); x++)
|
||||
{
|
||||
DWORD attr = 0;
|
||||
const DWORD flag = flags[x];
|
||||
const BOOL brc = SetFileAttributesW(name, flag);
|
||||
if (!brc)
|
||||
goto fail;
|
||||
|
||||
attr = GetFileAttributesW(name);
|
||||
if (flag != 0)
|
||||
{
|
||||
if ((attr & flag) == 0)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
DeleteFileW(name);
|
||||
free(name);
|
||||
free(base);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int TestSetFileAttributes(int argc, char* argv[])
|
||||
{
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
if (!test_SetFileAttributesA())
|
||||
return -1;
|
||||
if (!test_SetFileAttributesW())
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user