steam_helper: Create a thread to signal DIPC objects.

CW-Bug-Id: #15930
This commit is contained in:
Paul Gofman 2021-11-02 21:06:40 +03:00 committed by Arkadiusz Hiler
parent 5b7de85bdf
commit 7d37e79328

View file

@ -32,7 +32,10 @@
* a small subset of the actual Steam functionality for games that expect
* Windows version of Steam running. */
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include <windows.h>
#include <winternl.h>
#include <shlobj.h>
#include <string.h>
#include <stdio.h>
@ -1172,6 +1175,94 @@ static void setup_steam_files(void)
WINE_ERR("Could not write %s.\n", wine_dbgstr_w(libraryfolders_nameW));
}
#ifndef DIRECTORY_QUERY
#define DIRECTORY_QUERY 0x0001
#endif
static HANDLE find_ack_event(void)
{
static const WCHAR steam_ack_event[] = L"STEAM_START_ACK_EVENT";
static const WCHAR name[] = L"\\BaseNamedObjects\\Session\\1";
DIRECTORY_BASIC_INFORMATION *di;
OBJECT_ATTRIBUTES attr;
HANDLE dir, ret = NULL;
ULONG context, size;
UNICODE_STRING str;
char buffer[1024];
NTSTATUS status;
di = (DIRECTORY_BASIC_INFORMATION *)buffer;
RtlInitUnicodeString(&str, name);
InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
status = NtOpenDirectoryObject( &dir, DIRECTORY_QUERY, &attr );
if (status)
{
WINE_WARN("Failed to open directory %s, status %#x.\n", wine_dbgstr_w(name), status);
return NULL;
}
status = NtQueryDirectoryObject(dir, di, sizeof(buffer), TRUE, TRUE, &context, &size);
while (!status)
{
if (!strncmpW(di->ObjectName.Buffer, steam_ack_event, ARRAY_SIZE(steam_ack_event) - 1))
{
WINE_TRACE("Found event %s.\n", wine_dbgstr_w(di->ObjectName.Buffer));
ret = OpenEventW(SYNCHRONIZE, FALSE, di->ObjectName.Buffer);
if (!ret)
WINE_WARN("Failed to create event, err %u.\n", GetLastError());
break;
}
status = NtQueryDirectoryObject(dir, di, sizeof(buffer), TRUE, FALSE, &context, &size);
}
if (status && status != STATUS_NO_MORE_ENTRIES)
WINE_WARN("NtQueryDirectoryObject failed, status %#x.\n", status);
WINE_TRACE("ret %p.\n", ret);
CloseHandle(dir);
return ret;
}
static DWORD WINAPI steam_drm_thread(void *arg)
{
HANDLE consume, produce;
HANDLE start_ack = NULL;
HANDLE child = arg;
DWORD pid;
LONG prev;
consume = CreateSemaphoreA(NULL, 0, 512, "STEAM_DIPC_CONSUME");
if (!consume)
{
WINE_ERR("Failed to create consume semaphore, err %u.\n", GetLastError());
return -1;
}
produce = CreateSemaphoreA(NULL, 1, 512, "SREAM_DIPC_PRODUCE");
if (!produce)
{
CloseHandle(consume);
WINE_ERR("Failed to create produce semaphore, err %u.\n", GetLastError());
return -1;
}
pid = GetProcessId(child);
WINE_TRACE("Child pid %04x.\n", pid);
while (WaitForSingleObject(consume, INFINITE) == WAIT_OBJECT_0)
{
WINE_TRACE("Got event.\n");
if (!start_ack)
start_ack = find_ack_event();
if (start_ack)
SetEvent(start_ack);
ReleaseSemaphore(produce, 1, &prev);
WINE_TRACE("prev %d.\n", prev);
}
return 0;
}
int main(int argc, char *argv[])
{
HANDLE wait_handle = INVALID_HANDLE_VALUE;
@ -1240,6 +1331,9 @@ int main(int argc, char *argv[])
else
CloseHandle(child);
}
if (game_process)
CreateThread(NULL, 0, steam_drm_thread, child, 0, NULL);
}
if(wait_handle != INVALID_HANDLE_VALUE)