Milestone 5: deliver embedded RDP sessions and lifecycle hardening

This commit is contained in:
Keith Smith
2026-03-03 18:59:26 -07:00
parent 230a401386
commit 36006bd4aa
2941 changed files with 724359 additions and 77 deletions

View File

@@ -0,0 +1,23 @@
set(MODULE_NAME "TestPool")
set(MODULE_PREFIX "TEST_POOL")
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
set(${MODULE_PREFIX}_TESTS TestPoolIO.c TestPoolSynch.c TestPoolThread.c TestPoolTimer.c TestPoolWork.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}")
foreach(test ${${MODULE_PREFIX}_TESTS})
get_filename_component(TestName ${test} NAME_WE)
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
endforeach()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test")

View File

@@ -0,0 +1,8 @@
#include <winpr/crt.h>
#include <winpr/pool.h>
int TestPoolIO(int argc, char* argv[])
{
return 0;
}

View File

@@ -0,0 +1,8 @@
#include <winpr/crt.h>
#include <winpr/pool.h>
int TestPoolSynch(int argc, char* argv[])
{
return 0;
}

View File

@@ -0,0 +1,41 @@
#include <winpr/crt.h>
#include <winpr/pool.h>
/**
* Improve Scalability With New Thread Pool APIs:
* http://msdn.microsoft.com/en-us/magazine/cc16332.aspx
*
* Developing with Thread Pool Enhancements:
* http://msdn.microsoft.com/en-us/library/cc308561.aspx
*
* Introduction to the Windows Threadpool:
* http://blogs.msdn.com/b/harip/archive/2010/10/11/introduction-to-the-windows-threadpool-part-1.aspx
* http://blogs.msdn.com/b/harip/archive/2010/10/12/introduction-to-the-windows-threadpool-part-2.aspx
*/
int TestPoolThread(int argc, char* argv[])
{
TP_POOL* pool = nullptr;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
if (!(pool = CreateThreadpool(nullptr)))
{
printf("CreateThreadpool failed\n");
return -1;
}
if (!SetThreadpoolThreadMinimum(pool, 8)) /* default is 0 */
{
printf("SetThreadpoolThreadMinimum failed\n");
return -1;
}
SetThreadpoolThreadMaximum(pool, 64); /* default is 500 */
CloseThreadpool(pool);
return 0;
}

View File

@@ -0,0 +1,8 @@
#include <winpr/crt.h>
#include <winpr/pool.h>
int TestPoolTimer(int argc, char* argv[])
{
return 0;
}

View File

@@ -0,0 +1,134 @@
#include <winpr/wtypes.h>
#include <winpr/crt.h>
#include <winpr/pool.h>
#include <winpr/interlocked.h>
static LONG count = 0;
static void CALLBACK test_WorkCallback(PTP_CALLBACK_INSTANCE instance, void* context, PTP_WORK work)
{
printf("Hello %s: %03" PRId32 " (thread: 0x%08" PRIX32 ")\n", (char*)context,
InterlockedIncrement(&count), GetCurrentThreadId());
for (int index = 0; index < 100; index++)
{
BYTE a[1024];
BYTE b[1024];
BYTE c[1024] = WINPR_C_ARRAY_INIT;
FillMemory(a, ARRAYSIZE(a), 0xAA);
FillMemory(b, ARRAYSIZE(b), 0xBB);
CopyMemory(c, a, ARRAYSIZE(a));
CopyMemory(c, b, ARRAYSIZE(b));
}
}
static BOOL test1(void)
{
PTP_WORK work = nullptr;
printf("Global Thread Pool\n");
work = CreateThreadpoolWork(test_WorkCallback, "world", nullptr);
if (!work)
{
printf("CreateThreadpoolWork failure\n");
return FALSE;
}
/**
* You can post a work object one or more times (up to MAXULONG) without waiting for prior
* callbacks to complete. The callbacks will execute in parallel. To improve efficiency, the
* thread pool may throttle the threads.
*/
for (int index = 0; index < 10; index++)
SubmitThreadpoolWork(work);
WaitForThreadpoolWorkCallbacks(work, FALSE);
CloseThreadpoolWork(work);
return TRUE;
}
static BOOL test2(void)
{
BOOL rc = FALSE;
PTP_POOL pool = nullptr;
PTP_WORK work = nullptr;
PTP_CLEANUP_GROUP cleanupGroup = nullptr;
TP_CALLBACK_ENVIRON environment;
printf("Private Thread Pool\n");
if (!(pool = CreateThreadpool(nullptr)))
{
printf("CreateThreadpool failure\n");
return FALSE;
}
if (!SetThreadpoolThreadMinimum(pool, 4))
{
printf("SetThreadpoolThreadMinimum failure\n");
goto fail;
}
SetThreadpoolThreadMaximum(pool, 8);
InitializeThreadpoolEnvironment(&environment);
SetThreadpoolCallbackPool(&environment, pool);
cleanupGroup = CreateThreadpoolCleanupGroup();
if (!cleanupGroup)
{
printf("CreateThreadpoolCleanupGroup failure\n");
goto fail;
}
SetThreadpoolCallbackCleanupGroup(&environment, cleanupGroup, nullptr);
work = CreateThreadpoolWork(test_WorkCallback, "world", &environment);
if (!work)
{
printf("CreateThreadpoolWork failure\n");
goto fail;
}
for (int index = 0; index < 10; index++)
SubmitThreadpoolWork(work);
WaitForThreadpoolWorkCallbacks(work, FALSE);
rc = TRUE;
fail:
if (cleanupGroup)
{
CloseThreadpoolCleanupGroupMembers(cleanupGroup, TRUE, nullptr);
CloseThreadpoolCleanupGroup(cleanupGroup);
DestroyThreadpoolEnvironment(&environment);
/**
* See Remarks at
* https://msdn.microsoft.com/en-us/library/windows/desktop/ms682043(v=vs.85).aspx If there
* is a cleanup group associated with the work object, it is not necessary to call
* CloseThreadpoolWork ! calling the CloseThreadpoolCleanupGroupMembers function releases
* the work, wait, and timer objects associated with the cleanup group.
*/
// CloseThreadpoolWork(work); // this would segfault, see comment above. */
}
CloseThreadpool(pool);
return rc;
}
int TestPoolWork(int argc, char* argv[])
{
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
if (!test1())
return -1;
if (!test2())
return -1;
return 0;
}