fix race conditions, tests and some invalid return values
authorNorbert Federa <norbert.federa@thincast.com>
Wed, 1 Jun 2016 14:26:26 +0000 (16:26 +0200)
committerNorbert Federa <norbert.federa@thincast.com>
Wed, 1 Jun 2016 14:26:26 +0000 (16:26 +0200)
Since the current winpr implementation for overlapped operations is
incomplete and buggy, all affected functions will now fail if they are
called with a set FILE_FLAG_OVERLAPPED flag or a non-null pointer to
a OVERLAPPED structure.

winpr/nt:
- use proper one-time initialization on win32
- fix TestNtCreateFile
- fix broken/incomplete _RtlAnsiStringToUnicodeString
- unimplemented functions return appropriate error codes

winpr/pipe:
- improved TestPipeCreateNamedPipe
- rewrite the completely broken TestPipeCreateNamedPipeOverlapped test

rdtk:
- improve test and don't blindly return success

winpr/synch:
- fix race condition in TestSynchTimerQueue

winpr/ssspi:
- fix TestEnumerateSecurityPackages printf output
- fix TestQuerySecurityPackageInfo printf output

winpr/environment:
- fix GetEnvironmentStrings printf output

winpr/comm:
- unimplemented functions return appropriate error codes

winpr/io:
- unimplemented functions return appropriate error codes

winpr/thread:
- implement SwitchToThread() via sched_yield()

17 files changed:
rdtk/librdtk/test/TestRdTkNinePatch.c
winpr/libwinpr/comm/comm.c
winpr/libwinpr/comm/comm_ioctl.c
winpr/libwinpr/environment/test/TestEnvironmentGetEnvironmentStrings.c
winpr/libwinpr/file/file.c
winpr/libwinpr/file/namedPipeClient.c
winpr/libwinpr/io/io.c
winpr/libwinpr/nt/nt.c
winpr/libwinpr/nt/test/TestNtCreateFile.c
winpr/libwinpr/pipe/pipe.c
winpr/libwinpr/pipe/test/TestPipeCreateNamedPipe.c
winpr/libwinpr/pipe/test/TestPipeCreateNamedPipeOverlapped.c
winpr/libwinpr/sspi/test/TestEnumerateSecurityPackages.c
winpr/libwinpr/sspi/test/TestQuerySecurityPackageInfo.c
winpr/libwinpr/synch/test/TestSynchTimerQueue.c
winpr/libwinpr/synch/wait.c
winpr/libwinpr/thread/thread.c

index fb50dee..0550488 100644 (file)
@@ -3,11 +3,53 @@
 
 int TestRdTkNinePatch(int argc, char* argv[])
 {
-       rdtkEngine* engine;
+       rdtkEngine* engine = NULL;
+       rdtkSurface* surface = NULL;
+       DWORD scanline;
+       DWORD width;
+       DWORD height;
+       BYTE* data = NULL;
+       int ret = -1;
 
-       engine = rdtk_engine_new();
+       if (!(engine = rdtk_engine_new()))
+       {
+               printf("%s: error creating rdtk engine (%u)\n", __FUNCTION__, GetLastError());
+               goto out;
+       }
 
+       width = 1024;
+       height = 768;
+       scanline = width * 4;
+
+       /* let rdtk allocate the surface buffer */
+       if (!(surface = rdtk_surface_new(engine, NULL, width, height, scanline)))
+       {
+               printf("%s: error creating auto-allocated surface (%u)\n", __FUNCTION__, GetLastError());
+               goto out;
+       }
+       rdtk_surface_free(surface);
+       surface = NULL;
+
+
+       /* test self-allocated buffer */
+       if (!(data = calloc(height, scanline)))
+       {
+               printf("%s: error allocating surface buffer (%u)\n", __FUNCTION__, GetLastError());
+               goto out;
+       }
+
+       if (!(surface = rdtk_surface_new(engine, data, width, height, scanline)))
+       {
+               printf("%s: error creating self-allocated surface (%u)\n", __FUNCTION__, GetLastError());
+               goto out;
+       }
+
+       ret = 0;
+
+out:
+       rdtk_surface_free(surface);
        rdtk_engine_free(engine);
+       free(data);
 
-       return 0;
+       return ret;
 }
index dd1e386..b107b31 100644 (file)
@@ -149,7 +149,9 @@ BOOL BuildCommDCBA(LPCSTR lpDef, LPDCB lpDCB)
 
        /* TODO: not implemented */
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL BuildCommDCBW(LPCWSTR lpDef, LPDCB lpDCB)
@@ -159,7 +161,9 @@ BOOL BuildCommDCBW(LPCWSTR lpDef, LPDCB lpDCB)
 
        /* TODO: not implemented */
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL BuildCommDCBAndTimeoutsA(LPCSTR lpDef, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTimeouts)
@@ -169,7 +173,9 @@ BOOL BuildCommDCBAndTimeoutsA(LPCSTR lpDef, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTi
 
        /* TODO: not implemented */
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL BuildCommDCBAndTimeoutsW(LPCWSTR lpDef, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTimeouts)
@@ -179,7 +185,9 @@ BOOL BuildCommDCBAndTimeoutsW(LPCWSTR lpDef, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommT
 
        /* TODO: not implemented */
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL CommConfigDialogA(LPCSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC)
@@ -189,7 +197,9 @@ BOOL CommConfigDialogA(LPCSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC)
 
        /* TODO: not implemented */
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL CommConfigDialogW(LPCWSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC)
@@ -199,7 +209,9 @@ BOOL CommConfigDialogW(LPCWSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC)
 
        /* TODO: not implemented */
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL GetCommConfig(HANDLE hCommDev, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
@@ -214,7 +226,9 @@ BOOL GetCommConfig(HANDLE hCommDev, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
        if (!pComm)
                return FALSE;
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL SetCommConfig(HANDLE hCommDev, LPCOMMCONFIG lpCC, DWORD dwSize)
@@ -229,7 +243,9 @@ BOOL SetCommConfig(HANDLE hCommDev, LPCOMMCONFIG lpCC, DWORD dwSize)
        if (!pComm)
                return FALSE;
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL GetCommMask(HANDLE hFile, PDWORD lpEvtMask)
@@ -244,7 +260,9 @@ BOOL GetCommMask(HANDLE hFile, PDWORD lpEvtMask)
        if (!pComm)
                return FALSE;
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL SetCommMask(HANDLE hFile, DWORD dwEvtMask)
@@ -259,7 +277,9 @@ BOOL SetCommMask(HANDLE hFile, DWORD dwEvtMask)
        if (!pComm)
                return FALSE;
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL GetCommModemStatus(HANDLE hFile, PDWORD lpModemStat)
@@ -274,7 +294,9 @@ BOOL GetCommModemStatus(HANDLE hFile, PDWORD lpModemStat)
        if (!pComm)
                return FALSE;
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 /**
@@ -781,7 +803,9 @@ BOOL GetDefaultCommConfigA(LPCSTR lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
 
        /* TODO: not implemented */
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL GetDefaultCommConfigW(LPCWSTR lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
@@ -791,7 +815,9 @@ BOOL GetDefaultCommConfigW(LPCWSTR lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize
 
        /* TODO: not implemented */
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL SetDefaultCommConfigA(LPCSTR lpszName, LPCOMMCONFIG lpCC, DWORD dwSize)
@@ -801,7 +827,9 @@ BOOL SetDefaultCommConfigA(LPCSTR lpszName, LPCOMMCONFIG lpCC, DWORD dwSize)
 
        /* TODO: not implemented */
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL SetDefaultCommConfigW(LPCWSTR lpszName, LPCOMMCONFIG lpCC, DWORD dwSize)
@@ -811,7 +839,9 @@ BOOL SetDefaultCommConfigW(LPCWSTR lpszName, LPCOMMCONFIG lpCC, DWORD dwSize)
 
        /* TODO: not implemented */
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL SetCommBreak(HANDLE hFile)
@@ -826,7 +856,9 @@ BOOL SetCommBreak(HANDLE hFile)
        if (!pComm)
                return FALSE;
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL ClearCommBreak(HANDLE hFile)
@@ -841,7 +873,9 @@ BOOL ClearCommBreak(HANDLE hFile)
        if (!pComm)
                return FALSE;
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL ClearCommError(HANDLE hFile, PDWORD lpErrors, LPCOMSTAT lpStat)
@@ -856,7 +890,9 @@ BOOL ClearCommError(HANDLE hFile, PDWORD lpErrors, LPCOMSTAT lpStat)
        if (!pComm)
                return FALSE;
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 
@@ -923,7 +959,9 @@ BOOL EscapeCommFunction(HANDLE hFile, DWORD dwFunc)
        if (!pComm)
                return FALSE;
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL TransmitCommChar(HANDLE hFile, char cChar)
@@ -938,7 +976,9 @@ BOOL TransmitCommChar(HANDLE hFile, char cChar)
        if (!pComm)
                return FALSE;
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL WaitCommEvent(HANDLE hFile, PDWORD lpEvtMask, LPOVERLAPPED lpOverlapped)
@@ -953,7 +993,9 @@ BOOL WaitCommEvent(HANDLE hFile, PDWORD lpEvtMask, LPOVERLAPPED lpOverlapped)
        if (!pComm)
                return FALSE;
 
-       return TRUE;
+       CommLog_Print(WLOG_ERROR, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 
index 2438044..ed680a9 100644 (file)
@@ -78,9 +78,6 @@ static BOOL _CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID l
        WINPR_COMM* pComm = (WINPR_COMM*) hDevice;
        SERIAL_DRIVER* pServerSerialDriver = NULL;
 
-       /* clear any previous last error */
-       SetLastError(ERROR_SUCCESS);
-
        if (hDevice == INVALID_HANDLE_VALUE)
        {
                SetLastError(ERROR_INVALID_HANDLE);
@@ -93,7 +90,7 @@ static BOOL _CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID l
                return FALSE;
        }
 
-       if (lpOverlapped != NULL)
+       if (lpOverlapped)
        {
                SetLastError(ERROR_NOT_SUPPORTED);
                return FALSE;
@@ -105,6 +102,9 @@ static BOOL _CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID l
                return FALSE;
        }
 
+       /* clear any previous last error */
+       SetLastError(ERROR_SUCCESS);
+
        *lpBytesReturned = 0; /* will be ajusted if required ... */
 
        CommLog_Print(WLOG_DEBUG, "CommDeviceIoControl: IoControlCode: 0x%0.8x", dwIoControlCode);
index 1ef5534..238e5a2 100644 (file)
@@ -16,7 +16,7 @@ int TestEnvironmentGetEnvironmentStrings(int argc, char* argv[])
 
        while (p[0] && p[1])
        {
-               printf("%s\n", p);
+               _tprintf(_T("%s\n"), p);
                length = _tcslen(p);
                p += (length + 1);
        }
index d18a778..7641367 100644 (file)
@@ -150,15 +150,16 @@ static BOOL FileRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
        WINPR_FILE* file;
        BOOL status = TRUE;
 
-       if (!Object)
-               return FALSE;
-
        if (lpOverlapped)
        {
-               WLog_ERR(TAG, "Overlapping write not supported.");
+               WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
+               SetLastError(ERROR_NOT_SUPPORTED);
                return FALSE;
        }
 
+       if (!Object)
+               return FALSE;
+
        file = (WINPR_FILE *)Object;
        io_status = fread(lpBuffer, nNumberOfBytesToRead, 1, file->fp);
 
@@ -186,15 +187,16 @@ static BOOL FileWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrit
        size_t io_status;
        WINPR_FILE* file;
 
-       if (!Object)
-               return FALSE;
-
        if (lpOverlapped)
        {
-               WLog_ERR(TAG, "Overlapping write not supported.");
+               WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
+               SetLastError(ERROR_NOT_SUPPORTED);
                return FALSE;
        }
 
+       if (!Object)
+               return FALSE;
+
        file = (WINPR_FILE *)Object;
 
        io_status = fwrite(lpBuffer, nNumberOfBytesToWrite, 1, file->fp);
@@ -260,6 +262,13 @@ static BOOL FileLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved,
        int lock;
        WINPR_FILE* pFile = (WINPR_FILE*)hFile;
 
+       if (lpOverlapped)
+       {
+               WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
+               SetLastError(ERROR_NOT_SUPPORTED);
+               return FALSE;
+       }
+
        if (!hFile)
                return FALSE;
 
@@ -269,12 +278,6 @@ static BOOL FileLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved,
                return FALSE;
        }
 
-       if (lpOverlapped)
-       {
-               WLog_ERR(TAG, "lpOverlapped not implemented!");
-               return FALSE;
-       }
-
        if (dwFlags & LOCKFILE_EXCLUSIVE_LOCK)
                lock = LOCK_EX;
        else
@@ -324,6 +327,13 @@ static BOOL FileUnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfByte
 {
        WINPR_FILE* pFile = (WINPR_FILE*)hFile;
 
+       if (lpOverlapped)
+       {
+               WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
+               SetLastError(ERROR_NOT_SUPPORTED);
+               return FALSE;
+       }
+
        if (!hFile)
                return FALSE;
 
@@ -333,12 +343,6 @@ static BOOL FileUnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfByte
                return FALSE;
        }
 
-       if (lpOverlapped)
-       {
-               WLog_ERR(TAG, "lpOverlapped not implemented!");
-               return FALSE;
-       }
-
        if (flock(fileno(pFile->fp), LOCK_UN) < 0)
        {
                WLog_ERR(TAG, "flock(LOCK_UN) %s failed with %s [%08X]",
@@ -554,6 +558,13 @@ static HANDLE FileCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dw
        int lock = 0;
        FILE* fp = NULL;
 
+       if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
+       {
+               WLog_ERR(TAG, "WinPR %s does not support the FILE_FLAG_OVERLAPPED flag", __FUNCTION__);
+               SetLastError(ERROR_NOT_SUPPORTED);
+               return INVALID_HANDLE_VALUE;
+       }
+
        pFile = (WINPR_FILE*) calloc(1, sizeof(WINPR_FILE));
        if (!pFile)
        {
index a318c94..9c82788 100644 (file)
@@ -137,6 +137,13 @@ static HANDLE NamedPipeClientCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAcces
        struct sockaddr_un s;
        WINPR_NAMED_PIPE* pNamedPipe;
 
+       if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
+       {
+               WLog_ERR(TAG, "WinPR %s does not support the FILE_FLAG_OVERLAPPED flag", __FUNCTION__);
+               SetLastError(ERROR_NOT_SUPPORTED);
+               return INVALID_HANDLE_VALUE;
+       }
+
        if (!lpFileName)
                return INVALID_HANDLE_VALUE;
 
index 7b114ac..2aa5881 100644 (file)
 #include <sys/socket.h>
 
 #include <winpr/crt.h>
+#include <winpr/wlog.h>
 
 #include "../handle/handle.h"
-
 #include "../pipe/pipe.h"
+#include "../log.h"
+
+#define TAG WINPR_TAG("io")
 
 BOOL GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumberOfBytesTransferred, BOOL bWait)
 {
+#if 1
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
+#else
        ULONG Type;
        WINPR_HANDLE* Object;
 
@@ -118,54 +126,73 @@ BOOL GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumb
        }
 
        return TRUE;
+#endif
 }
 
 BOOL GetOverlappedResultEx(HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumberOfBytesTransferred, DWORD dwMilliseconds, BOOL bAlertable)
 {
-       return TRUE;
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
                LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
 {
-       return TRUE;
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 HANDLE CreateIoCompletionPort(HANDLE FileHandle, HANDLE ExistingCompletionPort, ULONG_PTR CompletionKey, DWORD NumberOfConcurrentThreads)
 {
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return NULL;
 }
 
 BOOL GetQueuedCompletionStatus(HANDLE CompletionPort, LPDWORD lpNumberOfBytesTransferred,
                PULONG_PTR lpCompletionKey, LPOVERLAPPED* lpOverlapped, DWORD dwMilliseconds)
 {
-       return TRUE;
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL GetQueuedCompletionStatusEx(HANDLE CompletionPort, LPOVERLAPPED_ENTRY lpCompletionPortEntries,
                ULONG ulCount, PULONG ulNumEntriesRemoved, DWORD dwMilliseconds, BOOL fAlertable)
 {
-       return TRUE;
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL PostQueuedCompletionStatus(HANDLE CompletionPort, DWORD dwNumberOfBytesTransferred, ULONG_PTR dwCompletionKey, LPOVERLAPPED lpOverlapped)
 {
-       return TRUE;
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL CancelIo(HANDLE hFile)
 {
-       return TRUE;
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL CancelIoEx(HANDLE hFile, LPOVERLAPPED lpOverlapped)
 {
-       return TRUE;
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL CancelSynchronousIo(HANDLE hThread)
 {
-       return TRUE;
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 #endif
@@ -180,29 +207,39 @@ BOOL GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumb
 BOOL DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
        LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
 {
-       return TRUE;
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 HANDLE CreateIoCompletionPort(HANDLE FileHandle, HANDLE ExistingCompletionPort, ULONG_PTR CompletionKey, DWORD NumberOfConcurrentThreads)
 {
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return NULL;
 }
 
 BOOL GetQueuedCompletionStatus(HANDLE CompletionPort, LPDWORD lpNumberOfBytesTransferred,
        PULONG_PTR lpCompletionKey, LPOVERLAPPED* lpOverlapped, DWORD dwMilliseconds)
 {
-       return TRUE;
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL GetQueuedCompletionStatusEx(HANDLE CompletionPort, LPOVERLAPPED_ENTRY lpCompletionPortEntries,
        ULONG ulCount, PULONG ulNumEntriesRemoved, DWORD dwMilliseconds, BOOL fAlertable)
 {
-       return TRUE;
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL PostQueuedCompletionStatus(HANDLE CompletionPort, DWORD dwNumberOfBytesTransferred, ULONG_PTR dwCompletionKey, LPOVERLAPPED lpOverlapped)
 {
-       return TRUE;
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL CancelIo(HANDLE hFile)
@@ -212,7 +249,9 @@ BOOL CancelIo(HANDLE hFile)
 
 BOOL CancelSynchronousIo(HANDLE hThread)
 {
-       return TRUE;
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 #endif
index 653b752..6d9dde9 100644 (file)
 
 #include <winpr/crt.h>
 #include <winpr/library.h>
-
+#include <winpr/wlog.h>
 #include <winpr/nt.h>
 
+#include "../log.h"
+#define TAG WINPR_TAG("nt")
+
+
 /**
  * NtXxx Routines:
  * http://msdn.microsoft.com/en-us/library/windows/hardware/ff557720/
@@ -160,31 +164,35 @@ NTSTATUS _RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString,
        int index;
 
        if (!SourceString)
-       {
-               _RtlInitUnicodeString(DestinationString, NULL);
-               return 0;
-       }
+               return STATUS_INVALID_PARAMETER;
 
        if (AllocateDestinationString)
        {
-               DestinationString->Length = SourceString->Length * 2;
-               DestinationString->MaximumLength = SourceString->MaximumLength * 2;
-
-               DestinationString->Buffer = (PWSTR) malloc(DestinationString->MaximumLength);
-               if (!DestinationString->Buffer)
-                       return STATUS_NO_MEMORY;
+               PWSTR wbuf = NULL;
 
-               for (index = 0; index < SourceString->MaximumLength; index++)
+               if (SourceString->MaximumLength)
                {
-                       DestinationString->Buffer[index] = (WCHAR) SourceString->Buffer[index];
+                       if (!(wbuf = (PWSTR) malloc(SourceString->MaximumLength * 2)))
+                               return STATUS_NO_MEMORY;
                }
+
+               DestinationString->MaximumLength = SourceString->MaximumLength * 2;
+               DestinationString->Buffer = wbuf;
        }
        else
        {
+               if (DestinationString->MaximumLength < SourceString->MaximumLength * 2)
+                       return STATUS_BUFFER_OVERFLOW;
+       }
 
+       for (index = 0; index < SourceString->MaximumLength; index++)
+       {
+               DestinationString->Buffer[index] = (WCHAR) SourceString->Buffer[index];
        }
 
-       return 0;
+       DestinationString->Length = SourceString->Length * 2;
+
+       return STATUS_SUCCESS;
 }
 
 /**
@@ -223,6 +231,10 @@ NTSTATUS _NtCreateFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess,
                PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess,
                ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength)
 {
+#if 1
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       return STATUS_NOT_SUPPORTED;
+#else
        WINPR_NT_FILE* pFileHandle;
 
        pFileHandle = (WINPR_NT_FILE*) calloc(1, sizeof(WINPR_NT_FILE));
@@ -243,6 +255,7 @@ NTSTATUS _NtCreateFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess,
        //STATUS_OBJECT_NAME_NOT_FOUND
 
        return STATUS_SUCCESS;
+#endif
 }
 
 /**
@@ -254,6 +267,10 @@ NTSTATUS _NtOpenFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess,
                POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock,
                ULONG ShareAccess, ULONG OpenOptions)
 {
+#if 1
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       return STATUS_NOT_SUPPORTED;
+#else
        WINPR_NT_FILE* pFileHandle;
 
        pFileHandle = (WINPR_NT_FILE*) calloc(1, sizeof(WINPR_NT_FILE));
@@ -267,6 +284,7 @@ NTSTATUS _NtOpenFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess,
        *((PULONG_PTR) FileHandle) = (ULONG_PTR) pFileHandle;
 
        return STATUS_SUCCESS;
+#endif
 }
 
 /**
@@ -277,7 +295,12 @@ NTSTATUS _NtOpenFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess,
 NTSTATUS _NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext,
                PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key)
 {
+#if 1
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       return STATUS_NOT_SUPPORTED;
+#else
        return STATUS_SUCCESS;
+#endif
 }
 
 /**
@@ -288,7 +311,12 @@ NTSTATUS _NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine
 NTSTATUS _NtWriteFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext,
                PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key)
 {
+#if 1
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       return STATUS_NOT_SUPPORTED;
+#else
        return STATUS_SUCCESS;
+#endif
 }
 
 /**
@@ -301,7 +329,12 @@ NTSTATUS _NtDeviceIoControlFile(HANDLE FileHandle, HANDLE Event,
                ULONG IoControlCode, PVOID InputBuffer, ULONG InputBufferLength,
                PVOID OutputBuffer, ULONG OutputBufferLength)
 {
-       return 0;
+#if 1
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       return STATUS_NOT_SUPPORTED;
+#else
+       return STATUS_SUCCESS;
+#endif
 }
 
 /**
@@ -311,16 +344,21 @@ NTSTATUS _NtDeviceIoControlFile(HANDLE FileHandle, HANDLE Event,
 
 NTSTATUS _NtClose(HANDLE Handle)
 {
+#if 1
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       return STATUS_NOT_SUPPORTED;
+#else
        WINPR_NT_FILE* pFileHandle;
 
        if (!Handle)
-               return 0;
+               return STATUS_SUCCESS;
 
        pFileHandle = (WINPR_NT_FILE*) Handle;
 
        free(pFileHandle);
 
        return STATUS_SUCCESS;
+#endif
 }
 
 /**
@@ -330,14 +368,17 @@ NTSTATUS _NtClose(HANDLE Handle)
 
 NTSTATUS _NtWaitForSingleObject(HANDLE Handle, BOOLEAN Alertable, PLARGE_INTEGER Timeout)
 {
-       return 0;
+#if 1
+       WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       return STATUS_NOT_SUPPORTED;
+#else
+       return STATUS_SUCCESS;
+#endif
 }
 
 #else
 
-static HMODULE NtdllModule = NULL;
-static BOOL moduleAvailable = FALSE;
-static BOOL moduleInitialized = FALSE;
+#include <winpr/synch.h>
 
 typedef VOID (WINAPI * RTL_INIT_ANSI_STRING_FN)(PANSI_STRING DestinationString, PCSZ SourceString);
 
@@ -387,36 +428,33 @@ static NT_DEVICE_IO_CONTROL_FILE_FN pNtDeviceIoControlFile = NULL;
 static NT_CLOSE_FN pNtClose = NULL;
 static NT_WAIT_FOR_SINGLE_OBJECT_FN pNtWaitForSingleObject = NULL;
 
-static void NtdllModuleInit()
-{
-       if (moduleInitialized)
-               return;
-
-       NtdllModule = LoadLibraryA("ntdll.dll");
-       moduleInitialized = TRUE;
+static INIT_ONCE ntdllInitOnce = INIT_ONCE_STATIC_INIT;
 
-       if (!NtdllModule)
-               return;
+static BOOL CALLBACK NtdllModuleInit(PINIT_ONCE once, PVOID param, PVOID *context)
+{
+       HMODULE NtdllModule = LoadLibraryA("ntdll.dll");
 
-       moduleAvailable = TRUE;
-
-       pRtlInitAnsiString = (RTL_INIT_ANSI_STRING_FN) GetProcAddress(NtdllModule, "RtlInitAnsiString");
-       pRtlInitUnicodeString = (RTL_INIT_UNICODE_STRING_FN) GetProcAddress(NtdllModule, "RtlInitUnicodeString");
-       pRtlAnsiStringToUnicodeString = (RTL_ANSI_STRING_TO_UNICODE_STRING_FN) GetProcAddress(NtdllModule, "RtlAnsiStringToUnicodeString");
-       pRtlFreeUnicodeString = (RTL_FREE_UNICODE_STRING_FN) GetProcAddress(NtdllModule, "RtlFreeUnicodeString");
-       pRtlNtStatusToDosError = (RTL_NT_STATUS_TO_DOS_ERROR_FN) GetProcAddress(NtdllModule, "RtlNtStatusToDosError");
-       pNtCreateFile = (NT_CREATE_FILE_FN) GetProcAddress(NtdllModule, "NtCreateFile");
-       pNtOpenFile = (NT_OPEN_FILE_FN) GetProcAddress(NtdllModule, "NtOpenFile");
-       pNtReadFile = (NT_READ_FILE_FN) GetProcAddress(NtdllModule, "NtReadFile");
-       pNtWriteFile = (NT_WRITE_FILE_FN) GetProcAddress(NtdllModule, "NtWriteFile");
-       pNtDeviceIoControlFile = (NT_DEVICE_IO_CONTROL_FILE_FN) GetProcAddress(NtdllModule, "NtDeviceIoControlFile");
-       pNtClose = (NT_CLOSE_FN) GetProcAddress(NtdllModule, "NtClose");
-       pNtWaitForSingleObject = (NT_WAIT_FOR_SINGLE_OBJECT_FN) GetProcAddress(NtdllModule, "NtWaitForSingleObject");
+       if (NtdllModule)
+       {
+               pRtlInitAnsiString = (RTL_INIT_ANSI_STRING_FN)GetProcAddress(NtdllModule, "RtlInitAnsiString");
+               pRtlInitUnicodeString = (RTL_INIT_UNICODE_STRING_FN)GetProcAddress(NtdllModule, "RtlInitUnicodeString");
+               pRtlAnsiStringToUnicodeString = (RTL_ANSI_STRING_TO_UNICODE_STRING_FN)GetProcAddress(NtdllModule, "RtlAnsiStringToUnicodeString");
+               pRtlFreeUnicodeString = (RTL_FREE_UNICODE_STRING_FN)GetProcAddress(NtdllModule, "RtlFreeUnicodeString");
+               pRtlNtStatusToDosError = (RTL_NT_STATUS_TO_DOS_ERROR_FN)GetProcAddress(NtdllModule, "RtlNtStatusToDosError");
+               pNtCreateFile = (NT_CREATE_FILE_FN)GetProcAddress(NtdllModule, "NtCreateFile");
+               pNtOpenFile = (NT_OPEN_FILE_FN)GetProcAddress(NtdllModule, "NtOpenFile");
+               pNtReadFile = (NT_READ_FILE_FN)GetProcAddress(NtdllModule, "NtReadFile");
+               pNtWriteFile = (NT_WRITE_FILE_FN)GetProcAddress(NtdllModule, "NtWriteFile");
+               pNtDeviceIoControlFile = (NT_DEVICE_IO_CONTROL_FILE_FN)GetProcAddress(NtdllModule, "NtDeviceIoControlFile");
+               pNtClose = (NT_CLOSE_FN)GetProcAddress(NtdllModule, "NtClose");
+               pNtWaitForSingleObject = (NT_WAIT_FOR_SINGLE_OBJECT_FN)GetProcAddress(NtdllModule, "NtWaitForSingleObject");
+       }
+       return TRUE;
 }
 
 VOID _RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
 {
-       NtdllModuleInit();
+       InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL);
 
        if (!pRtlInitAnsiString)
                return;
@@ -426,7 +464,7 @@ VOID _RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
 
 VOID _RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
 {
-       NtdllModuleInit();
+       InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL);
 
        if (!pRtlInitUnicodeString)
                return;
@@ -437,7 +475,7 @@ VOID _RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceStrin
 NTSTATUS _RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString,
                PCANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
 {
-       NtdllModuleInit();
+       InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL);
 
        if (!pRtlAnsiStringToUnicodeString)
                return STATUS_INTERNAL_ERROR;
@@ -448,7 +486,7 @@ NTSTATUS _RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString,
 
 VOID _RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
 {
-       NtdllModuleInit();
+       InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL);
 
        if (!pRtlFreeUnicodeString)
                return;
@@ -458,7 +496,7 @@ VOID _RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
 
 ULONG _RtlNtStatusToDosError(NTSTATUS status)
 {
-       NtdllModuleInit();
+       InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL);
 
        if (!pRtlNtStatusToDosError)
                return status;
@@ -471,7 +509,7 @@ NTSTATUS _NtCreateFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess,
                PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess,
                ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength)
 {
-       NtdllModuleInit();
+       InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL);
 
        if (!pNtCreateFile)
                return STATUS_INTERNAL_ERROR;
@@ -485,7 +523,7 @@ NTSTATUS _NtOpenFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess,
                POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock,
                ULONG ShareAccess, ULONG OpenOptions)
 {
-       NtdllModuleInit();
+       InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL);
 
        if (!pNtOpenFile)
                return STATUS_INTERNAL_ERROR;
@@ -497,7 +535,7 @@ NTSTATUS _NtOpenFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess,
 NTSTATUS _NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext,
                PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key)
 {
-       NtdllModuleInit();
+       InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL);
 
        if (!pNtReadFile)
                return STATUS_INTERNAL_ERROR;
@@ -509,7 +547,7 @@ NTSTATUS _NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine
 NTSTATUS _NtWriteFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext,
                PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key)
 {
-       NtdllModuleInit();
+       InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL);
 
        if (!pNtWriteFile)
                return STATUS_INTERNAL_ERROR;
@@ -523,7 +561,7 @@ NTSTATUS _NtDeviceIoControlFile(HANDLE FileHandle, HANDLE Event,
                ULONG IoControlCode, PVOID InputBuffer, ULONG InputBufferLength,
                PVOID OutputBuffer, ULONG OutputBufferLength)
 {
-       NtdllModuleInit();
+       InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL);
 
        if (!pNtDeviceIoControlFile)
                return STATUS_INTERNAL_ERROR;
@@ -535,7 +573,7 @@ NTSTATUS _NtDeviceIoControlFile(HANDLE FileHandle, HANDLE Event,
 
 NTSTATUS _NtClose(HANDLE Handle)
 {
-       NtdllModuleInit();
+       InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL);
 
        if (!pNtClose)
                return STATUS_INTERNAL_ERROR;
@@ -545,7 +583,7 @@ NTSTATUS _NtClose(HANDLE Handle)
 
 NTSTATUS _NtWaitForSingleObject(HANDLE Handle, BOOLEAN Alertable, PLARGE_INTEGER Timeout)
 {
-       NtdllModuleInit();
+       InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL);
 
        if (!pNtWaitForSingleObject)
                return STATUS_INTERNAL_ERROR;
index d91bf22..2097177 100644 (file)
@@ -3,6 +3,12 @@
 
 #include <winpr/nt.h>
 
+#ifdef _WIN32
+#define TESTFILE "\\??\\C:\\Documents and Settings\\All Users\\winpr_test_nt_create_file.txt"
+#else
+#define TESTFILE "/tmp/winpr_test_nt_create_file.txt"
+#endif
+
 int TestNtCreateFile(int argc, char* argv[])
 {
        HANDLE handle;
@@ -15,8 +21,22 @@ int TestNtCreateFile(int argc, char* argv[])
        OBJECT_ATTRIBUTES attributes;
        IO_STATUS_BLOCK ioStatusBlock;
 
-       _RtlInitAnsiString(&aString, "\\??\\C:\\Users\\Public\\foo.txt");
-       _RtlAnsiStringToUnicodeString(&uString, &aString, TRUE);
+       int eFailure = -1;
+       int eSuccess =  0;
+
+#ifndef _WIN32
+       printf("Note: %s result may currently only be trusted on Win32\n", __FUNCTION__);
+       eFailure = eSuccess;
+#endif
+
+       _RtlInitAnsiString(&aString, TESTFILE);
+
+       ntstatus = _RtlAnsiStringToUnicodeString(&uString, &aString, TRUE);
+       if (ntstatus != STATUS_SUCCESS)
+       {
+               printf("_RtlAnsiStringToUnicodeString failure: 0x%08X\n", ntstatus);
+               return eFailure;
+       }
 
        handle = NULL;
        ZeroMemory(&ioStatusBlock, sizeof(IO_STATUS_BLOCK));
@@ -32,8 +52,8 @@ int TestNtCreateFile(int argc, char* argv[])
 
        if (ntstatus != STATUS_SUCCESS)
        {
-               printf("NtCreateFile failure: 0x%04X\n", ntstatus);
-               return -1;
+               printf("_NtCreateFile failure: 0x%08X\n", ntstatus);
+               return eFailure;
        }
 
        _RtlFreeUnicodeString(&uString);
@@ -42,9 +62,9 @@ int TestNtCreateFile(int argc, char* argv[])
 
        if (ntstatus != STATUS_SUCCESS)
        {
-               printf("NtClose failure: 0x%04X\n", ntstatus);
-               return -1;
+               printf("_NtClose failure: 0x%08X\n", ntstatus);
+               return eFailure;
        }
 
-       return 0;
+       return eSuccess;
 }
index 0d8a6b6..399c2d4 100644 (file)
@@ -125,6 +125,13 @@ static BOOL PipeRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
        WINPR_PIPE* pipe;
        BOOL status = TRUE;
 
+       if (lpOverlapped)
+       {
+               WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
+               SetLastError(ERROR_NOT_SUPPORTED);
+               return FALSE;
+       }
+
        pipe = (WINPR_PIPE *)Object;
        do
        {
@@ -156,6 +163,13 @@ static BOOL PipeWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrit
        int io_status;
        WINPR_PIPE* pipe;
 
+       if (lpOverlapped)
+       {
+               WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
+               SetLastError(ERROR_NOT_SUPPORTED);
+               return FALSE;
+       }
+
        pipe = (WINPR_PIPE *)Object;
 
        do
@@ -253,6 +267,13 @@ BOOL NamedPipeRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
        WINPR_NAMED_PIPE* pipe;
        BOOL status = TRUE;
 
+       if (lpOverlapped)
+       {
+               WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
+               SetLastError(ERROR_NOT_SUPPORTED);
+               return FALSE;
+       }
+
        pipe = (WINPR_NAMED_PIPE *)Object;
 
        if (!(pipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
@@ -340,6 +361,13 @@ BOOL NamedPipeWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
        WINPR_NAMED_PIPE* pipe;
        BOOL status = TRUE;
 
+       if (lpOverlapped)
+       {
+               WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
+               SetLastError(ERROR_NOT_SUPPORTED);
+               return FALSE;
+       }
+
        pipe = (WINPR_NAMED_PIPE*) Object;
 
        if (!(pipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
@@ -537,6 +565,13 @@ HANDLE CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD
        int serverfd = -1;
        NamedPipeServerSocketEntry* baseSocket = NULL;
 
+       if (dwOpenMode & FILE_FLAG_OVERLAPPED)
+       {
+               WLog_ERR(TAG, "WinPR %s does not support the FILE_FLAG_OVERLAPPED flag", __FUNCTION__);
+               SetLastError(ERROR_NOT_SUPPORTED);
+               return INVALID_HANDLE_VALUE;
+       }
+
        if (!lpName)
                return INVALID_HANDLE_VALUE;
 
@@ -688,6 +723,8 @@ out:
 HANDLE CreateNamedPipeW(LPCWSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances,
                                                DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
 {
+       WLog_ERR(TAG, "%s is not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return NULL;
 }
 
@@ -698,6 +735,13 @@ BOOL ConnectNamedPipe(HANDLE hNamedPipe, LPOVERLAPPED lpOverlapped)
        struct sockaddr_un s;
        WINPR_NAMED_PIPE* pNamedPipe;
 
+       if (lpOverlapped)
+       {
+               WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
+               SetLastError(ERROR_NOT_SUPPORTED);
+               return FALSE;
+       }
+
        if (!hNamedPipe)
                return FALSE;
 
@@ -755,14 +799,16 @@ BOOL PeekNamedPipe(HANDLE hNamedPipe, LPVOID lpBuffer, DWORD nBufferSize,
                                   LPDWORD lpBytesRead, LPDWORD lpTotalBytesAvail, LPDWORD lpBytesLeftThisMessage)
 {
        WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
-       return TRUE;
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL TransactNamedPipe(HANDLE hNamedPipe, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
                                           DWORD nOutBufferSize, LPDWORD lpBytesRead, LPOVERLAPPED lpOverlapped)
 {
        WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
-       return TRUE;
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL WaitNamedPipeA(LPCSTR lpNamedPipeName, DWORD nTimeOut)
@@ -805,7 +851,8 @@ BOOL WaitNamedPipeA(LPCSTR lpNamedPipeName, DWORD nTimeOut)
 BOOL WaitNamedPipeW(LPCWSTR lpNamedPipeName, DWORD nTimeOut)
 {
        WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
-       return TRUE;
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
 }
 
 BOOL SetNamedPipeHandleState(HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout)
@@ -850,18 +897,21 @@ BOOL SetNamedPipeHandleState(HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCol
 BOOL ImpersonateNamedPipeClient(HANDLE hNamedPipe)
 {
        WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return FALSE;
 }
 
 BOOL GetNamedPipeClientComputerNameA(HANDLE Pipe, LPCSTR ClientComputerName, ULONG ClientComputerNameLength)
 {
        WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return FALSE;
 }
 
 BOOL GetNamedPipeClientComputerNameW(HANDLE Pipe, LPCWSTR ClientComputerName, ULONG ClientComputerNameLength)
 {
        WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return FALSE;
 }
 
index 21b4fb3..4595784 100644 (file)
@@ -446,6 +446,17 @@ int TestPipeCreateNamedPipe(int argc, char* argv[])
        HANDLE SingleThread;
        HANDLE ClientThread;
        HANDLE ServerThread;
+       HANDLE hPipe;
+
+       /* Verify that CreateNamedPipe returns INVALID_HANDLE_VALUE on failure */
+       hPipe = CreateNamedPipeA(NULL, 0, 0, 0, 0, 0, 0, NULL);
+       if (hPipe != INVALID_HANDLE_VALUE)
+       {
+               printf("CreateNamedPipe unexpectedly returned %p instead of INVALID_HANDLE_VALUE (%p)\n",
+                       hPipe, INVALID_HANDLE_VALUE);
+               return -1;
+       }
+
 #ifndef _WIN32
        signal(SIGPIPE, SIG_IGN);
 #endif
index ecb8bdf..2ce09b2 100644 (file)
 #include <winpr/thread.h>
 
 #define PIPE_BUFFER_SIZE       32
+#define PIPE_TIMEOUT_MS                20000   // 20 seconds
 
-static HANDLE ReadyEvent;
+BYTE SERVER_MESSAGE[PIPE_BUFFER_SIZE];
+BYTE CLIENT_MESSAGE[PIPE_BUFFER_SIZE];
+
+BOOL bClientSuccess = FALSE;
+BOOL bServerSuccess = FALSE;
+
+static HANDLE serverReadyEvent;
 
 static LPTSTR lpszPipeName = _T("\\\\.\\pipe\\winpr_test_pipe_overlapped");
 
@@ -22,65 +29,86 @@ static void* named_pipe_client_thread(void* arg)
        HANDLE hEvent = NULL;
        HANDLE hNamedPipe = NULL;
        BYTE* lpReadBuffer = NULL;
-       BYTE* lpWriteBuffer = NULL;
        BOOL fSuccess = FALSE;
        OVERLAPPED overlapped;
        DWORD nNumberOfBytesToRead;
        DWORD nNumberOfBytesToWrite;
        DWORD NumberOfBytesTransferred;
 
-       WaitForSingleObject(ReadyEvent, INFINITE);
-       hNamedPipe = CreateFile(lpszPipeName, GENERIC_READ | GENERIC_WRITE,
-                               0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+       status = WaitForSingleObject(serverReadyEvent, PIPE_TIMEOUT_MS);
+       if (status != WAIT_OBJECT_0)
+       {
+               printf("client: failed to wait for server ready event: %u\n", status);
+               goto finish;
+       }
+
 
-       if (!hNamedPipe)
+       /* 1: initialize overlapped structure */
+
+       ZeroMemory(&overlapped, sizeof(OVERLAPPED));
+       if (!(hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
        {
-               printf("Named Pipe CreateFile failure: NULL handle\n");
+               printf("client: CreateEvent failure: %u\n", GetLastError());
                goto finish;
        }
+       overlapped.hEvent = hEvent;
+
+
+       /* 2: connect to server named pipe */
+
+       hNamedPipe = CreateFile(lpszPipeName, GENERIC_READ | GENERIC_WRITE,
+                        0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
 
        if (hNamedPipe == INVALID_HANDLE_VALUE)
        {
-               printf("Named Pipe CreateFile failure: INVALID_HANDLE_VALUE\n");
+               printf("client: Named Pipe CreateFile failure: %u\n", GetLastError());
                goto finish;
        }
 
-       lpReadBuffer = (BYTE*) malloc(PIPE_BUFFER_SIZE);
-       lpWriteBuffer = (BYTE*) malloc(PIPE_BUFFER_SIZE);
-       if (!lpReadBuffer || !lpWriteBuffer)
+
+       /* 3: write to named pipe */
+
+       nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
+       NumberOfBytesTransferred = 0;
+
+       fSuccess = WriteFile(hNamedPipe, CLIENT_MESSAGE, nNumberOfBytesToWrite, NULL, &overlapped);
+
+       if (!fSuccess)
+               fSuccess = (GetLastError() == ERROR_IO_PENDING);
+
+       if (!fSuccess)
        {
-               printf("Error allocating memory\n");
+               printf("client: NamedPipe WriteFile failure (initial): %u\n", GetLastError());
                goto finish;
        }
-       ZeroMemory(&overlapped, sizeof(OVERLAPPED));
 
-       if (!(hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
+       status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
+       if (status != WAIT_OBJECT_0)
        {
-               printf("CreateEvent failure: (%d)\n", GetLastError());
+               printf("client: failed to wait for overlapped event (write): %u\n", status);
                goto finish;
        }
 
-       overlapped.hEvent = hEvent;
-       nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
-       FillMemory(lpWriteBuffer, PIPE_BUFFER_SIZE, 0x59);
-       fSuccess = WriteFile(hNamedPipe, lpWriteBuffer, nNumberOfBytesToWrite, NULL, &overlapped);
-
+       fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, FALSE);
        if (!fSuccess)
-               fSuccess = (GetLastError() == ERROR_IO_PENDING);
+       {
+               printf("client: NamedPipe WriteFile failure (final): %u\n", GetLastError());
+               goto finish;
+       }
+       printf("client: WriteFile transferred %u bytes:\n", NumberOfBytesTransferred);
 
-       if (!fSuccess)
+
+       /* 4: read from named pipe */
+
+       if (!(lpReadBuffer = (BYTE*)calloc(1, PIPE_BUFFER_SIZE)))
        {
-               printf("Client NamedPipe WriteFile failure: %d\n", GetLastError());
+               printf("client: Error allocating read buffer\n");
                goto finish;
        }
 
-       status = WaitForMultipleObjects(1, &hEvent, FALSE, INFINITE);
-       NumberOfBytesTransferred = 0;
-       fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, TRUE);
-       printf("Client GetOverlappedResult: fSuccess: %d NumberOfBytesTransferred: %d\n",
-               fSuccess, NumberOfBytesTransferred);
        nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
-       ZeroMemory(lpReadBuffer, PIPE_BUFFER_SIZE);
+       NumberOfBytesTransferred = 0;
+
        fSuccess = ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, NULL, &overlapped);
 
        if (!fSuccess)
@@ -88,21 +116,38 @@ static void* named_pipe_client_thread(void* arg)
 
        if (!fSuccess)
        {
-               printf("Client NamedPipe ReadFile failure: %d\n", GetLastError());
+               printf("client: NamedPipe ReadFile failure (initial): %u\n", GetLastError());
+               goto finish;
+       }
+
+       status = WaitForMultipleObjects(1, &hEvent, FALSE, PIPE_TIMEOUT_MS);
+       if (status != WAIT_OBJECT_0)
+       {
+               printf("client: failed to wait for overlapped event (read): %u\n", status);
                goto finish;
        }
 
-       status = WaitForMultipleObjects(1, &hEvent, FALSE, INFINITE);
-       NumberOfBytesTransferred = 0;
        fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, TRUE);
-       printf("Client GetOverlappedResult: fSuccess: %d NumberOfBytesTransferred: %d\n",
-               fSuccess, NumberOfBytesTransferred);
-       printf("Client ReadFile (%d):\n", NumberOfBytesTransferred);
+       if (!fSuccess)
+       {
+               printf("client: NamedPipe ReadFile failure (final): %u\n", GetLastError());
+               goto finish;
+       }
+
+       printf("client: ReadFile transferred %u bytes:\n", NumberOfBytesTransferred);
        winpr_HexDump("pipe.test", WLOG_DEBUG, lpReadBuffer, NumberOfBytesTransferred);
 
+       if (NumberOfBytesTransferred != PIPE_BUFFER_SIZE || memcmp(lpReadBuffer, SERVER_MESSAGE, PIPE_BUFFER_SIZE))
+       {
+               printf("client: received unexpected data from server\n");
+               goto finish;
+       }
+
+       printf("client: finished successfully\n");
+       bClientSuccess = TRUE;
+
 finish:
        free(lpReadBuffer);
-       free(lpWriteBuffer);
        if (hNamedPipe)
                CloseHandle(hNamedPipe);
        if (hEvent)
@@ -114,71 +159,103 @@ finish:
 static void* named_pipe_server_thread(void* arg)
 {
        DWORD status;
-       HANDLE hEvent;
-       HANDLE hNamedPipe;
-       BYTE* lpReadBuffer;
-       BYTE* lpWriteBuffer;
+       HANDLE hEvent = NULL;
+       HANDLE hNamedPipe = NULL;
+       BYTE* lpReadBuffer = NULL;
        OVERLAPPED overlapped;
        BOOL fSuccess = FALSE;
        BOOL fConnected = FALSE;
        DWORD nNumberOfBytesToRead;
        DWORD nNumberOfBytesToWrite;
        DWORD NumberOfBytesTransferred;
-       hNamedPipe = CreateNamedPipe(lpszPipeName,
-                                                                PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
-                                                                PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, 0, NULL);
 
-       if (!hNamedPipe)
+       /* 1: initialize overlapped structure */
+
+       ZeroMemory(&overlapped, sizeof(OVERLAPPED));
+       if (!(hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
        {
-               printf("CreateNamedPipe failure: NULL handle\n");
-               return NULL;
+               printf("server: CreateEvent failure: %u\n", GetLastError());
+               SetEvent(serverReadyEvent); /* unblock client thread */
+               goto finish;
        }
+       overlapped.hEvent = hEvent;
+
+
+       /* 2: create named pipe and set ready event */
+
+       hNamedPipe = CreateNamedPipe(lpszPipeName,
+                       PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
+                       PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, 0, NULL);
 
        if (hNamedPipe == INVALID_HANDLE_VALUE)
        {
-               printf("CreateNamedPipe failure: INVALID_HANDLE_VALUE (%d)\n", GetLastError());
-               return NULL;
+               printf("server: CreateNamedPipe failure: %u\n", GetLastError());
+               SetEvent(serverReadyEvent); /* unblock client thread */
+               goto finish;
        }
 
-       SetEvent(ReadyEvent);
-       ZeroMemory(&overlapped, sizeof(OVERLAPPED));
+       SetEvent(serverReadyEvent);
 
-       if (!(hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
-       {
-               printf("CreateEvent failure: (%d)\n", GetLastError());
-               return NULL;
-       }
+       /* 3: connect named pipe */
+
+#if 0
+       /* This sleep will most certainly cause ERROR_PIPE_CONNECTED below */
+       Sleep(2000);
+#endif
 
-       overlapped.hEvent = hEvent;
        fConnected = ConnectNamedPipe(hNamedPipe, &overlapped);
-       printf("ConnectNamedPipe status: %d\n", GetLastError());
+       status = GetLastError();
+
+       /**
+        * At this point if fConnected is FALSE, we have to check GetLastError() for:
+        * ERROR_PIPE_CONNECTED:
+        *     client has already connected before we have called ConnectNamedPipe.
+        *     this is quite common depending on the timings and indicates success
+        * ERROR_IO_PENDING:
+        *     Since we're using ConnectNamedPipe asynchronously here, the function returns
+        *     immediately and this error code simply indicates that the operation is
+        *     still in progress. Hence we have to wait for the completion event and use
+        *     GetOverlappedResult to query the actual result of the operation (note that
+        *     the lpNumberOfBytesTransferred parameter is undefined/useless for a
+        *     ConnectNamedPipe operation)
+        */
 
        if (!fConnected)
-               fConnected = (GetLastError() == ERROR_IO_PENDING);
+               fConnected = (status == ERROR_PIPE_CONNECTED);
 
-       status = WaitForMultipleObjects(1, &hEvent, FALSE, INFINITE);
-       NumberOfBytesTransferred = 0;
-       fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, TRUE);
-       printf("Server GetOverlappedResult: fSuccess: %d NumberOfBytesTransferred: %d\n", fSuccess, NumberOfBytesTransferred);
+       printf("server: ConnectNamedPipe status: %u\n", status);
+
+       if (!fConnected && status == ERROR_IO_PENDING)
+       {
+               DWORD dwDummy;
+               printf("server: waiting up to %u ms for connection ...\n", PIPE_TIMEOUT_MS);
+               status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
+               if (status == WAIT_OBJECT_0)
+                       fConnected = GetOverlappedResult(hNamedPipe, &overlapped, &dwDummy, FALSE);
+               else
+                       printf("server: failed to wait for overlapped event (connect): %u\n", status);
+       }
 
        if (!fConnected)
        {
-               printf("ConnectNamedPipe failure: %d\n", GetLastError());
-               CloseHandle(hNamedPipe);
-               CloseHandle(hEvent);
-               return NULL;
+               printf("server: ConnectNamedPipe failed: %u\n", status);
+               goto finish;
        }
 
-       lpReadBuffer = (BYTE*) calloc(1, PIPE_BUFFER_SIZE);
-       lpWriteBuffer = (BYTE*) malloc(PIPE_BUFFER_SIZE);
-       if (!lpReadBuffer || !lpWriteBuffer)
+       printf("server: named pipe successfully connected\n");
+
+
+       /* 4: read from named pipe */
+
+       if (!(lpReadBuffer = (BYTE*)calloc(1, PIPE_BUFFER_SIZE)))
        {
-               printf("Error allocating memory\n");
-               free(lpReadBuffer);
-               free(lpWriteBuffer);
-               return NULL;
+               printf("server: Error allocating read buffer\n");
+               goto finish;
        }
+
        nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
+       NumberOfBytesTransferred = 0;
+
        fSuccess = ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, NULL, &overlapped);
 
        if (!fSuccess)
@@ -186,45 +263,74 @@ static void* named_pipe_server_thread(void* arg)
 
        if (!fSuccess)
        {
-               printf("Server NamedPipe ReadFile failure: %d\n", GetLastError());
-               free(lpReadBuffer);
-               free(lpWriteBuffer);
-               CloseHandle(hNamedPipe);
-               CloseHandle(hEvent);
-               return NULL;
+               printf("server: NamedPipe ReadFile failure (initial): %u\n", GetLastError());
+               goto finish;
        }
 
-       status = WaitForMultipleObjects(1, &hEvent, FALSE, INFINITE);
-       NumberOfBytesTransferred = 0;
-       fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, TRUE);
-       printf("Server GetOverlappedResult: fSuccess: %d NumberOfBytesTransferred: %d\n", fSuccess, NumberOfBytesTransferred);
-       printf("Server ReadFile (%d):\n", NumberOfBytesTransferred);
+       status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
+       if (status != WAIT_OBJECT_0)
+       {
+               printf("server: failed to wait for overlapped event (read): %u\n", status);
+               goto finish;
+       }
+
+       fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, FALSE);
+       if (!fSuccess)
+       {
+               printf("server: NamedPipe ReadFile failure (final): %u\n", GetLastError());
+               goto finish;
+       }
+
+       printf("server: ReadFile transferred %u bytes:\n", NumberOfBytesTransferred);
        winpr_HexDump("pipe.test", WLOG_DEBUG, lpReadBuffer, NumberOfBytesTransferred);
+
+       if (NumberOfBytesTransferred != PIPE_BUFFER_SIZE || memcmp(lpReadBuffer, CLIENT_MESSAGE, PIPE_BUFFER_SIZE))
+       {
+               printf("server: received unexpected data from client\n");
+               goto finish;
+       }
+
+
+       /* 5: write to named pipe */
+
        nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
-       FillMemory(lpWriteBuffer, PIPE_BUFFER_SIZE, 0x45);
-       fSuccess = WriteFile(hNamedPipe, lpWriteBuffer, nNumberOfBytesToWrite, NULL, &overlapped);
+       NumberOfBytesTransferred = 0;
+
+       fSuccess = WriteFile(hNamedPipe, SERVER_MESSAGE, nNumberOfBytesToWrite, NULL, &overlapped);
 
        if (!fSuccess)
                fSuccess = (GetLastError() == ERROR_IO_PENDING);
 
        if (!fSuccess)
        {
-               printf("Server NamedPipe WriteFile failure: %d\n", GetLastError());
-               free(lpReadBuffer);
-               free(lpWriteBuffer);
-               CloseHandle(hNamedPipe);
-               CloseHandle(hEvent);
-               return NULL;
+               printf("server: NamedPipe WriteFile failure (initial): %u\n", GetLastError());
+               goto finish;
        }
 
-       status = WaitForMultipleObjects(1, &hEvent, FALSE, INFINITE);
-       NumberOfBytesTransferred = 0;
-       fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, TRUE);
-       printf("Server GetOverlappedResult: fSuccess: %d NumberOfBytesTransferred: %d\n", fSuccess, NumberOfBytesTransferred);
-       free(lpReadBuffer);
-       free(lpWriteBuffer);
+       status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
+       if (status != WAIT_OBJECT_0)
+       {
+               printf("server: failed to wait for overlapped event (write): %u\n", status);
+               goto finish;
+       }
+
+       fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, FALSE);
+       if (!fSuccess)
+       {
+               printf("server: NamedPipe WriteFile failure (final): %u\n", GetLastError());
+               goto finish;
+       }
+
+       printf("server: WriteFile transferred %u bytes:\n", NumberOfBytesTransferred);
+       //winpr_HexDump("pipe.test", WLOG_DEBUG, lpWriteBuffer, NumberOfBytesTransferred);
+
+       bServerSuccess = TRUE;
+       printf("server: finished successfully\n");
+
+finish:
        CloseHandle(hNamedPipe);
        CloseHandle(hEvent);
+       free(lpReadBuffer);
        return NULL;
 }
 
@@ -232,26 +338,38 @@ int TestPipeCreateNamedPipeOverlapped(int argc, char* argv[])
 {
        HANDLE ClientThread;
        HANDLE ServerThread;
+       int eFailure = -1;
+       int eSuccess =  0;
+
+#ifndef _WIN32
+        printf("Note: %s result may currently only be trusted on Win32\n", __FUNCTION__);
+        eFailure = eSuccess;
+#endif
 
-       if (!(ReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
+       FillMemory(SERVER_MESSAGE, PIPE_BUFFER_SIZE, 0xAA);
+       FillMemory(CLIENT_MESSAGE, PIPE_BUFFER_SIZE, 0xBB);
+
+       if (!(serverReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
        {
                printf("CreateEvent failed: %d\n", GetLastError());
-               return -1;
+               return eFailure;
        }
        if (!(ClientThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_client_thread, NULL, 0, NULL)))
        {
                printf("CreateThread (client) failed: %d\n", GetLastError());
-               return -1;
+               return eFailure;
        }
        if (!(ServerThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_server_thread, NULL, 0, NULL)))
        {
                printf("CreateThread (server) failed: %d\n", GetLastError());
-               return -1;
+               return eFailure;
        }
 
        WaitForSingleObject(ClientThread, INFINITE);
        WaitForSingleObject(ServerThread, INFINITE);
 
-       /* FIXME: Since this function always returns 0 this test is very much useless */
-       return 0;
+       if (bClientSuccess && bServerSuccess)
+               return eSuccess;
+
+       return eFailure;
 }
index 8cca3e3..b705101 100644 (file)
@@ -3,6 +3,7 @@
 #include <winpr/crt.h>
 #include <winpr/sspi.h>
 #include <winpr/winpr.h>
+#include <winpr/tchar.h>
 
 int TestEnumerateSecurityPackages(int argc, char* argv[])
 {
@@ -21,11 +22,11 @@ int TestEnumerateSecurityPackages(int argc, char* argv[])
                return -1;      
        }
 
-       printf("\nEnumerateSecurityPackages (%d):\n", (unsigned int)cPackages);
+       _tprintf(_T("\nEnumerateSecurityPackages (%d):\n"), (unsigned int)cPackages);
 
        for (index = 0; index < (int) cPackages; index++)
        {
-               printf("\"%s\", \"%s\"\n", pPackageInfo[index].Name, pPackageInfo[index].Comment);
+               _tprintf(_T("\"%s\", \"%s\"\n"), pPackageInfo[index].Name, pPackageInfo[index].Comment);
        }
 
        FreeContextBuffer(pPackageInfo);
index 5f970fd..a85797f 100644 (file)
@@ -2,6 +2,7 @@
 #include <stdio.h>
 #include <winpr/sspi.h>
 #include <winpr/winpr.h>
+#include <winpr/tchar.h>
 
 int TestQuerySecurityPackageInfo(int argc, char* argv[])
 {
@@ -18,8 +19,8 @@ int TestQuerySecurityPackageInfo(int argc, char* argv[])
                return -1;
        }
 
-       printf("\nQuerySecurityPackageInfo:\n");
-       printf("\"%s\", \"%s\"\n", pPackageInfo->Name, pPackageInfo->Comment);
+       _tprintf(_T("\nQuerySecurityPackageInfo:\n"));
+       _tprintf(_T("\"%s\", \"%s\"\n"), pPackageInfo->Name, pPackageInfo->Comment);
 
        sspi_GlobalFinish();
 
index 3b77735..761eafc 100644 (file)
@@ -1,7 +1,7 @@
 
 #include <winpr/crt.h>
 #include <winpr/sysinfo.h>
-
+#include <winpr/file.h>
 #include <winpr/synch.h>
 
 #define FIRE_COUNT     5
@@ -92,16 +92,20 @@ int TestSynchTimerQueue(int argc, char* argv[])
                        printf("Failed to wait for timer queue timer #%u (%u)\n", index, GetLastError());
                        return -1;
                }
-               CloseHandle(apcData[index].CompletionEvent);
        }
 
        for (index = 0; index < TIMER_COUNT; index++)
        {
-               if (!DeleteTimerQueueTimer(hTimerQueue, hTimers[index], NULL))
+               /**
+                * Note: If the CompletionEvent parameter is INVALID_HANDLE_VALUE, the function waits
+                * for any running timer callback functions to complete before returning.
+                */
+               if (!DeleteTimerQueueTimer(hTimerQueue, hTimers[index], INVALID_HANDLE_VALUE))
                {
                        printf("DeleteTimerQueueTimer failed (%u)\n", GetLastError());
                        return -1;
                }
+               CloseHandle(apcData[index].CompletionEvent);
        }
 
        if (!DeleteTimerQueue(hTimerQueue))
index 41fa929..b8a4dc6 100644 (file)
@@ -285,9 +285,9 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
 
 DWORD WaitForSingleObjectEx(HANDLE hHandle, DWORD dwMilliseconds, BOOL bAlertable)
 {
-       WLog_ERR(TAG, "Function not implemented.");
-       assert(0);
-       return WAIT_OBJECT_0;
+       WLog_ERR(TAG, "%s: Not implemented.");
+       SetLastError(ERROR_NOT_SUPPORTED);
+       return WAIT_FAILED;
 }
 
 DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE *lpHandles, BOOL bWaitAll, DWORD dwMilliseconds)
@@ -525,9 +525,9 @@ DWORD WaitForMultipleObjectsEx(DWORD nCount, const HANDLE *lpHandles, BOOL bWait
 
 DWORD SignalObjectAndWait(HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL bAlertable)
 {
-       WLog_ERR(TAG, "Function not implemented.");
-       assert(0);
-       return 0;
+       WLog_ERR(TAG, "%s: Not implemented.");
+       SetLastError(ERROR_NOT_SUPPORTED);
+       return WAIT_FAILED;
 }
 
 #endif
index 39eaa35..54b4310 100644 (file)
@@ -566,7 +566,8 @@ BOOL ThreadCloseHandle(HANDLE handle)
 HANDLE CreateRemoteThread(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize,
                                                  LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId)
 {
-       WLog_ERR(TAG, "not implemented");
+       WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
        return NULL;
 }
 
@@ -698,14 +699,14 @@ DWORD ResumeThread(HANDLE hThread)
 
 DWORD SuspendThread(HANDLE hThread)
 {
-       WLog_ERR(TAG, "Function not implemented!");
-       return 0;
+       WLog_ERR(TAG, "%s: not implemented", __FUNCTION__);
+       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return (DWORD)-1;
 }
 
 BOOL SwitchToThread(VOID)
 {
-       WLog_ERR(TAG, "Function not implemented!");
-       return TRUE;
+       return (sched_yield() == 0);
 }
 
 BOOL TerminateThread(HANDLE hThread, DWORD dwExitCode)