From d02606aaa6cbdbb1939cfe99b6d5f013af5c48a6 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 25 Dec 2014 12:36:28 -0700
Subject: ntdll: Add stubs for WinSqmStartSession / WinSqmEndSession.

Based on a patch by Detlef Riekenberg.
---
 dlls/ntdll/misc.c      | 20 +++++++++++++++++++
 dlls/ntdll/ntdll.spec  |  2 ++
 dlls/ntdll/tests/rtl.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 76 insertions(+)

diff --git a/dlls/ntdll/misc.c b/dlls/ntdll/misc.c
index 5469116..4517aec 100644
--- a/dlls/ntdll/misc.c
+++ b/dlls/ntdll/misc.c
@@ -27,6 +27,8 @@
 #include <sys/utsname.h>
 #endif
 
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
 #include "windows.h"
 #include "wmistr.h"
 #include "evntrace.h"
@@ -332,6 +334,15 @@ void * __cdecl _lfind( const void *key, const void *base, unsigned int *nmemb,
 }
 
 /*********************************************************************
+ *                  WinSqmEndSession   (NTDLL.@)
+ */
+NTSTATUS WINAPI WinSqmEndSession(PVOID unknown1)
+{
+    FIXME("(%p) stub!\n", unknown1);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+/*********************************************************************
  *                  WinSqmIsOptedIn   (NTDLL.@)
  */
 BOOL WINAPI WinSqmIsOptedIn(void)
@@ -341,6 +352,15 @@ BOOL WINAPI WinSqmIsOptedIn(void)
 }
 
 /*********************************************************************
+ *                  WinSqmStartSession   (NTDLL.@)
+ */
+PVOID WINAPI WinSqmStartSession(PVOID unknown1, DWORD unknown2, DWORD unknown3)
+{
+    FIXME("(%p, 0x%x, 0x%x) stub!\n", unknown1, unknown2, unknown3);
+    return NULL;
+}
+
+/*********************************************************************
  *                  EtwEventRegister   (NTDLL.@)
  */
 ULONG WINAPI EtwEventRegister( LPCGUID provider, PENABLECALLBACK callback, PVOID context, PREGHANDLE handle )
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index d6ded19..0c23514 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -1011,7 +1011,9 @@
 @ stdcall TpWaitForWait(ptr long)
 @ stdcall TpWaitForWork(ptr long)
 @ stdcall -ret64 VerSetConditionMask(int64 long long)
+@ stdcall WinSqmEndSession(ptr)
 @ stdcall WinSqmIsOptedIn()
+@ stdcall WinSqmStartSession(ptr long long)
 @ stdcall ZwAcceptConnectPort(ptr long ptr long long ptr) NtAcceptConnectPort
 @ stdcall ZwAccessCheck(ptr long long ptr ptr ptr ptr ptr) NtAccessCheck
 @ stdcall ZwAccessCheckAndAuditAlarm(ptr long ptr ptr ptr long ptr long ptr ptr ptr) NtAccessCheckAndAuditAlarm
diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c
index 94a22ac..d382691 100644
--- a/dlls/ntdll/tests/rtl.c
+++ b/dlls/ntdll/tests/rtl.c
@@ -62,6 +62,9 @@ static inline USHORT __my_ushort_swap(USHORT s)
 
 /* Function ptrs for ntdll calls */
 static HMODULE hntdll = 0;
+static PVOID     (WINAPI *pWinSqmStartSession)(PVOID unknown1, DWORD unknown2, DWORD unknown3);
+static BOOL      (WINAPI *pWinSqmIsOptedIn)(void);
+static NTSTATUS  (WINAPI *pWinSqmEndSession)(PVOID unknown1);
 static SIZE_T    (WINAPI  *pRtlCompareMemory)(LPCVOID,LPCVOID,SIZE_T);
 static SIZE_T    (WINAPI  *pRtlCompareMemoryUlong)(PULONG, SIZE_T, ULONG);
 static NTSTATUS  (WINAPI  *pRtlDeleteTimer)(HANDLE, HANDLE, HANDLE);
@@ -115,6 +118,9 @@ static void InitFunctionPtrs(void)
     hntdll = LoadLibraryA("ntdll.dll");
     ok(hntdll != 0, "LoadLibrary failed\n");
     if (hntdll) {
+        pWinSqmStartSession = (void *)GetProcAddress(hntdll, "WinSqmStartSession");
+        pWinSqmIsOptedIn = (void *)GetProcAddress(hntdll, "WinSqmIsOptedIn");
+        pWinSqmEndSession = (void *)GetProcAddress(hntdll, "WinSqmEndSession");
 	pRtlCompareMemory = (void *)GetProcAddress(hntdll, "RtlCompareMemory");
 	pRtlCompareMemoryUlong = (void *)GetProcAddress(hntdll, "RtlCompareMemoryUlong");
         pRtlDeleteTimer = (void *)GetProcAddress(hntdll, "RtlDeleteTimer");
@@ -161,6 +167,48 @@ static void InitFunctionPtrs(void)
     ok(strlen(src) == 15, "Source must be 16 bytes long!\n");
 }
 
+#ifdef __i386__
+const char stdcall3_thunk[] =
+    "\x56"              /* push %esi */
+    "\x89\xE6"          /* mov %esp, %esi */
+    "\xFF\x74\x24\x14"  /* pushl 20(%esp) */
+    "\xFF\x74\x24\x14"  /* pushl 20(%esp) */
+    "\xFF\x74\x24\x14"  /* pushl 20(%esp) */
+    "\xFF\x54\x24\x14"  /* calll 20(%esp) */
+    "\x89\xF0"          /* mov %esi, %eax */
+    "\x29\xE0"          /* sub %esp, %eax */
+    "\x89\xF4"          /* mov %esi, %esp */
+    "\x5E"              /* pop %esi */
+    "\xC2\x10\x00"      /* ret $16 */
+;
+
+static INT (WINAPI *call_stdcall_func3)(PVOID func, PVOID arg0, DWORD arg1, DWORD arg2) = NULL;
+
+static void test_WinSqm(void)
+{
+    INT args;
+
+    if (!pWinSqmStartSession)
+    {
+        win_skip("WinSqmStartSession() is not available\n");
+        return;
+    }
+
+    call_stdcall_func3 = (void*) VirtualAlloc( NULL, sizeof(stdcall3_thunk) - 1, MEM_COMMIT,
+                                               PAGE_EXECUTE_READWRITE );
+    memcpy( call_stdcall_func3, stdcall3_thunk, sizeof(stdcall3_thunk) - 1 );
+
+    args = 3 - call_stdcall_func3( pWinSqmStartSession, NULL, 0, 0 ) / 4;
+    ok(args == 3, "WinSqmStartSession expected to take %d arguments instead of 3\n", args);
+    args = 3 - call_stdcall_func3( pWinSqmIsOptedIn, NULL, 0, 0 ) / 4;
+    ok(args == 0, "WinSqmIsOptedIn expected to take %d arguments instead of 0\n", args);
+    args = 3 - call_stdcall_func3( pWinSqmEndSession, NULL, 0, 0 ) / 4;
+    ok(args == 1, "WinSqmEndSession expected to take %d arguments instead of 1\n", args);
+
+    VirtualFree( call_stdcall_func3, 0, MEM_RELEASE );
+}
+#endif
+
 #define COMP(str1,str2,cmplen,len) size = pRtlCompareMemory(str1, str2, cmplen); \
   ok(size == len, "Expected %ld, got %ld\n", size, (SIZE_T)len)
 
@@ -2060,6 +2108,12 @@ START_TEST(rtl)
 {
     InitFunctionPtrs();
 
+#ifdef __i386__
+    test_WinSqm();
+#else
+    skip("stdcall-style parameter checks are not supported on this platform.\n");
+#endif
+
     test_RtlCompareMemory();
     test_RtlCompareMemoryUlong();
     test_RtlMoveMemory();
-- 
2.6.4

