diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/.bzrignore posixrdp/posixxrdp.orig/.bzrignore --- xrdp/xrdp-0.5.0~20100303cvs.orig/.bzrignore 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/.bzrignore 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,2 @@ +RE:.*CVS +RE:.*CVS/.* diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/arch.h posixrdp/posixxrdp.orig/common/arch.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/arch.h 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/arch.h 2010-11-08 09:56:43.000000000 +0100 @@ -1,5 +1,5 @@ /* - Copyright (c) 2004-2010 Jay Sorg + Copyright (c) 2004-2009 Jay Sorg Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -24,21 +24,25 @@ #if !defined(ARCH_H) #define ARCH_H -#if !(defined(L_ENDIAN) || defined(B_ENDIAN)) /* check endianess */ -#if defined(__sparc__) || defined(__PPC__) || defined(__ppc__) || \ - defined(__hppa__) +#if defined(__sparc__) || defined(__PPC__) || defined(__ppc__) #define B_ENDIAN +#elif defined(__BYTE_ORDER) +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define L_ENDIAN +#elif __BYTE_ORDER == __BIG_ENDIAN +#define B_ENDIAN +#endif #else #define L_ENDIAN #endif + /* check if we need to align data */ #if defined(__sparc__) || defined(__alpha__) || defined(__hppa__) || \ defined(__AIX__) || defined(__PPC__) || defined(__mips__) || \ - defined(__ia64__) || defined(__ppc__) || defined(__arm__) + defined(__ia64__) || defined(__ppc__) #define NEED_ALIGN #endif -#endif /* defines for thread creation factory functions */ #if defined(_WIN32) diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/crc32.c posixrdp/posixxrdp.orig/common/crc32.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/crc32.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/crc32.c 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,100 @@ +/*----------------------------------------------------------------------------*\ + * CRC-32 version 2.0.0RDP created 2010-03-15, based on + * CRC-32 version 2.0.0 by Craig Bruce, 2006-04-29. + * + * This function generates the CRC-32 values for the files named in the + * command-line arguments. These are the same CRC-32 values used by GZIP, + * PKZIP, and ZMODEM. The Crc32_ComputeBuf() can also be detached and + * used independently. + * + * Based on the byte-oriented implementation "File Verification Using CRC" + * by Mark R. Nelson in Dr. Dobb's Journal, May 1992, pp. 64-67. + * + * v1.0.0: original release. + * v1.0.1: fixed printf formats. + * v1.0.2: fixed something else. + * v1.0.3: replaced CRC constant table by generator function. + * v1.0.4: reformatted code, made ANSI C. 1994-12-05. + * v2.0.0: rewrote to use memory buffer & static table, 2006-04-29. + * v2.0.0RDP: modified for use in xrdp by Ryan Rafferty, 2010-03-15. +\*----------------------------------------------------------------------------*/ + +#include +#include +#include + +#include "crc32.h" + +/*----------------------------------------------------------------------------*\ + * NAME: + * Crc32_ComputeBuf() - computes the CRC-32 value of a memory buffer + * DESCRIPTION: + * Computes or accumulates the CRC-32 value for a memory buffer. + * The 'inCrc32' gives a previously accumulated CRC-32 value to allow + * a CRC to be generated for multiple sequential buffer-fuls of data. + * The 'inCrc32' for the first buffer must be zero. + * ARGUMENTS: + * inCrc32 - accumulated CRC-32 value, must be 0 on first call + * buf - buffer to compute CRC-32 value for + * bufLen - number of bytes in buffer + * RETURNS: + * crc32 - computed CRC-32 value + * ERRORS: + * (no errors are possible) +\*----------------------------------------------------------------------------*/ + +uint32_t Crc32_ComputeBuf( uint32_t inCrc32, const void * buf, size_t bufLen ) { + static const uint32_t crcTable[256] = { + 0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535, + 0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD, + 0xE7B82D07,0x90BF1D91,0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D, + 0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC, + 0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,0x3B6E20C8,0x4C69105E,0xD56041E4, + 0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C, + 0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,0x26D930AC, + 0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F, + 0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB, + 0xB6662D3D,0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F, + 0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB, + 0x086D3D2D,0x91646C97,0xE6635C01,0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E, + 0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,0x8BBEB8EA, + 0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,0x4DB26158,0x3AB551CE, + 0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB,0x4369E96A, + 0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9, + 0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409, + 0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81, + 0xB7BD5C3B,0xC0BA6CAD,0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739, + 0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8, + 0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,0xF00F9344,0x8708A3D2,0x1E01F268, + 0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0, + 0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,0xD6D6A3E8, + 0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B, + 0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF, + 0x4669BE79,0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703, + 0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7, + 0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A, + 0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE, + 0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,0x86D3D2D4,0xF1D4E242, + 0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,0x88085AE6, + 0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45, + 0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D, + 0x3E6E77DB,0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5, + 0x47B2CF7F,0x30B5FFE9,0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605, + 0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94, + 0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D }; + uint32_t crc32 = 0; + size_t i = 0; + uint8_t * byteBuf = (uint8_t *)NULL; + + /** accumulate crc32 for buffer **/ + byteBuf = (uint8_t *)buf; + crc32 = inCrc32 ^ 0xFFFFFFFF; + for (i = 0; i < bufLen; i++) { + crc32 = (crc32 >> 8) ^ (crcTable[ ((crc32 ^ byteBuf[i]) & 0xFF) ]); + } + return( crc32 ^ 0xFFFFFFFF ); +} + +/*----------------------------------------------------------------------------*\ + * END OF MODULE: crc32.c +\*----------------------------------------------------------------------------*/ diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/crc32.h posixrdp/posixxrdp.orig/common/crc32.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/crc32.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/crc32.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,19 @@ +#ifndef __RDP_CRC32__ +#define __RDP_CRC32__ + +#include +#include +#include + + +/*----------------------------------------------------------------------------*\ + * Function prototypes +\*----------------------------------------------------------------------------*/ + +uint32_t Crc32_ComputeBuf( uint32_t inCrc32, const void * buf, size_t bufLen ); + +/*----------------------------------------------------------------------------*\ + * End of crc32.h +\*----------------------------------------------------------------------------*/ + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/dbg.c posixrdp/posixxrdp.orig/common/dbg.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/dbg.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/dbg.c 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,40 @@ +#include "dbg.h" +#include "thread_calls.h" +#include "thread_macros.h" + +static tc_t g_tc_mutex; // = TC_MUTEX_INITIALIZER; +static tc_p mutex_tc = (tc_p)(&g_tc_mutex); +static unsigned int taskq_count = 0; + +void DBGLOG(const char * _itype, const char * _itxt) { + char taskq_text[256]; + FILE * taskq = NULL; + const char * deflt = "/tmp/taskq.log"; + + snprintf(taskq_text,255,"%s",deflt); + if (_itype != NULL && (unsigned int)_itype > 100) { + if (strlen(_itype) > 0) { + snprintf(taskq_text,255,"%s%s%s","/tmp/taskq_",_itype,".log"); + } + } + + if (!strcmp(_itype,"drdynvc") || !strcmp(_itype,"trans") || !strcmp(_itype,"rdpport") || !strcmp(_itype,"rdpfs") || !strcmp(_itype,"port") || !strcmp(_itype,"child") || !strcmp(_itype,"parent") || !strcmp(_itype,"xrdp") || !strcmp(_itype,"sound") || !strcmp(_itype,"rdprec") || !strcmp(_itype,"chansrv") || !strcmp(_itype,"clipboard") || !strcmp(_itype,"net") || !strcmp(_itype,"sesman") || !strcmp(_itype,"redir") || !strncmp(_itype,"libscp",strlen("libscp"))) + { + taskq = fopen(taskq_text,"a"); + if (taskq!=NULL) { + + TC_MUTEX_LOCK(mutex_tc); + + if (taskq_count==0) { + fprintf(taskq,"\n*********\n"); + } + fprintf(taskq," (%d) ",taskq_count); + fprintf(taskq,"%s\n",_itxt); + taskq_count++; + + TC_MUTEX_UNLOCK(mutex_tc); + + fclose(taskq); + } + } +} diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/dbg.h posixrdp/posixxrdp.orig/common/dbg.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/dbg.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/dbg.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,46 @@ +#ifndef __taskq__ +#define __taskq__ + +#include +#include +#include +#include + +#define DBGTIMESTRING "(%s, %s %d, %d:%.2d)" + +#define MDBGLOG(dest, ...) { \ + time_t mdbglog_rawtime; \ + struct tm * mdbglog_tm; \ + char mdbglog_mtbuf[512]; \ + char mdbglog_tbuf[512]; \ + char mdbglog_rbuf[512]; \ + char mdbglog_datebuf[256]; \ + g_memset(&mdbglog_rawtime, 0x00, sizeof(time_t)); \ + g_memset(mdbglog_mtbuf, 0x00, sizeof(mdbglog_mtbuf)); \ + g_memset(mdbglog_tbuf, 0x00, sizeof(mdbglog_tbuf)); \ + g_memset(mdbglog_rbuf, 0x00, sizeof(mdbglog_rbuf)); \ + g_memset(mdbglog_datebuf, 0x00, sizeof(mdbglog_datebuf)); \ + mdbglog_rawtime = g_time(0); \ + mdbglog_tm = localtime(&mdbglog_rawtime); \ + if (mdbglog_tm != NULL) { \ + /* strftime(mdbglog_datebuf, sizeof(mdbglog_datebuf), nl_langinfo (D_T_FMT), mdbglog_tm); */ \ + g_snprintf(mdbglog_mtbuf,sizeof(mdbglog_mtbuf), __VA_ARGS__); \ + /* g_snprintf(mdbglog_tbuf,sizeof(mdbglog_tbuf),"%s",mdbglog_datebuf); */ \ + /* g_snprintf(mdbglog_rbuf,sizeof(mdbglog_rbuf),"%s %s",mdbglog_tbuf,mdbglog_mtbuf); */ \ + /* g_snprintf(mdbglog_rbuf,sizeof(mdbglog_rbuf),"%s",mdbglog_mtbuf); */ \ + DBGLOG(dest,mdbglog_mtbuf); \ + } \ +} + +#define VLOG(...) MDBGLOG("vnc", __VA_ARGS__) +#define NLOG(...) MDBGLOG("net", __VA_ARGS__) +#define SLOG(...) MDBGLOG("sound", __VA_ARGS__) +#define CLOG(...) MDBGLOG("chansrv", __VA_ARGS__) +#define DLOG(...) MDBGLOG("devredir", __VA_ARGS__) + +//unsigned int taskq_count; +/* char mtbuf[512]; */ + +void DBGLOG(const char *, const char *); + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/defines.h posixrdp/posixxrdp.orig/common/defines.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/defines.h 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/defines.h 2010-11-08 09:56:43.000000000 +0100 @@ -20,9 +20,12 @@ */ -#if !defined(DEFINES_H) +#ifndef DEFINES_H #define DEFINES_H +#define HAVE_PULSE_AUDIO +#define _XRDP_ENABLE_I18N_ + /* check for debug */ #ifdef XRDP_DEBUG #define DEBUG(args) g_writeln args; @@ -48,12 +51,18 @@ #define RECTOFFSET(r, dx, dy) \ { (r).left += dx; (r).top += dy; (r).right += dx; (r).bottom += dy; } #define GETPIXEL8(d, x, y, w) (*(((unsigned char*)d) + ((y) * (w) + (x)))) +#define GETPIXEL15(d, x, y, w) (*(((unsigned short*)d) + ((y) * (w) + (x)))) #define GETPIXEL16(d, x, y, w) (*(((unsigned short*)d) + ((y) * (w) + (x)))) +#define GETPIXEL24(d, x, y, w) (*(((unsigned int*)d) + ((y) * (w) + (x)))) #define GETPIXEL32(d, x, y, w) (*(((unsigned int*)d) + ((y) * (w) + (x)))) #define SETPIXEL8(d, x, y, w, v) \ (*(((unsigned char*)d) + ((y) * (w) + (x))) = (v)) +#define SETPIXEL15(d, x, y, w, v) \ +(*(((unsigned short*)d) + ((y) * (w) + (x))) = (v)) #define SETPIXEL16(d, x, y, w, v) \ (*(((unsigned short*)d) + ((y) * (w) + (x))) = (v)) +#define SETPIXEL24(d, x, y, w, v) \ +(*(((unsigned int*)d) + ((y) * (w) + (x))) = (v)) #define SETPIXEL32(d, x, y, w, v) \ (*(((unsigned int*)d) + ((y) * (w) + (x))) = (v)) #define COLOR8(r, g, b) \ @@ -66,17 +75,19 @@ #define COLOR16(r, g, b) ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3)) #define COLOR24RGB(r, g, b) (((r) << 16) | ((g) << 8) | (b)) #define COLOR24BGR(r, g, b) (((b) << 16) | ((g) << 8) | (r)) +#define COLOR32RGB(r, g, b) (((r) << 16) | ((g) << 8) | (b)) +#define COLOR32BGR(r, g, b) (((b) << 24) | ((g) << 16) | ((r) << 8)) #define SPLITCOLOR15(r, g, b, c) \ { \ - r = (((c) >> 7) & 0xf8) | (((c) >> 12) & 0x7); \ - g = (((c) >> 2) & 0xf8) | (((c) >> 8) & 0x7); \ - b = (((c) << 3) & 0xf8) | (((c) >> 2) & 0x7); \ + r = c & 0x7C00; \ + g = c & 0x3E00; \ + b = c & 0x001F; \ } #define SPLITCOLOR16(r, g, b, c) \ { \ - r = (((c) >> 8) & 0xf8) | (((c) >> 13) & 0x7); \ - g = (((c) >> 3) & 0xfc) | (((c) >> 9) & 0x3); \ - b = (((c) << 3) & 0xf8) | (((c) >> 2) & 0x7); \ + r = c & 0xF800; \ + g = c & 0x07E0; \ + b = c & 0x001F; \ } #define SPLITCOLOR32(r, g, b, c) \ { \ @@ -91,3 +102,52 @@ #define USE_CRC #endif + +#ifndef __G_MACROS_H__ +#ifndef __XRDP_G_MACROS__ +#define __XRDP_G_MACROS__ + +/* + * The G_LIKELY and G_UNLIKELY macros let the programmer give hints to + * the compiler about the expected result of an expression. Some compilers + * can use this information for optimizations. + * + * The _G_BOOLEAN_EXPR macro is intended to trigger a gcc warning when + * putting assignments in g_return_if_fail (). + */ +#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) +#define _G_BOOLEAN_EXPR(expr) \ +__extension__ ({ \ +int _g_boolean_var_; \ +if (expr) \ +_g_boolean_var_ = 1; \ +else \ +_g_boolean_var_ = 0; \ +_g_boolean_var_; \ +}) +#define G_LIKELY(expr) (__builtin_expect (_G_BOOLEAN_EXPR(expr), 1)) +#define G_UNLIKELY(expr) (__builtin_expect (_G_BOOLEAN_EXPR(expr), 0)) +#else +#define G_LIKELY(expr) (expr) +#define G_UNLIKELY(expr) (expr) +#endif + +#endif /* __XRDP_G_MACROS__ */ +#endif /* __G_MACROS_H__ */ + + +#ifndef __XRDP_STREAMS_DEFS__ +#define __XRDP_STREAMS_DEFS__ + +#define MAX_STREAM 65528 +/* #define MAX_STREAM 8192 */ +#define MAX_PDU_LENGTH_TOTAL 65528 +#define MAX_PDU_LENGTH_OLD (MAX_STREAM - 32) +#define MAX_PDU_LENGTH ((MAX_STREAM / 2) - 32) + +#define WO_UNSPEC 0 +#define WO_INET 1 +#define WO_LOCAL 2 +#define WO_FIFO 3 + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/devredir_defs.h posixrdp/posixxrdp.orig/common/devredir_defs.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/devredir_defs.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/devredir_defs.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,1504 @@ + +#ifndef __XRDP_DEVREDIR_DEFS_H__ +#define __XRDP_DEVREDIR_DEFS_H__ + +#include +#include "defines.h" +#include "ntstatus.h" +#include "arch.h" +#include "parse.h" +#include "sound_defs.h" +#include "trans.h" +#include "thread_calls.h" + +#ifndef BYTE +#define BYTE uint8_t +#endif +#ifndef WORD +#define WORD uint16_t +#endif +#ifndef DWORD +#define DWORD uint32_t +#endif +#ifndef QWORD +#define QWORD uint64_t +#endif + +#ifndef RDPDR_DTYP_SERIAL +#define RDPDR_DTYP_SERIAL 0x00000001 +#endif +#ifndef RDPDR_DTYP_PARALLEL +#define RDPDR_DTYP_PARALLEL 0x00000002 +#endif +#ifndef RDPDR_DTYP_PRINT +#define RDPDR_DTYP_PRINT 0x00000004 +#endif +#ifndef RDPDR_DTYP_FILESYSTEM +#define RDPDR_DTYP_FILESYSTEM 0x00000008 +#endif +#ifndef RDPDR_DTYP_SMARTCARD +#define RDPDR_DTYP_SMARTCARD 0x00000020 +#endif + +typedef union _NTSTATUS { + DWORD Value; + struct _Fields { + unsigned int Sev:2; + unsigned int C:1; + unsigned int N:1; + unsigned int Facility:12; + WORD Code; + } Fields; + +} NTSTATUS; + +typedef struct _callback { + + int callback_index; + int FileId; + int length; + void * data; + + int opid; /* the opid assigned by "get_opid()" */ + struct _rdpfs * fs; /* pointer to the filesystem to which the original operation pertains */ + struct _rdpport * port; /* pointer to the port to which the original operation pertains */ + struct _rdpprint * printer; /* pointer to the printer to which the original operation pertains */ + struct _rdpsc * smartcard; /* pointer to the smartcard to which the original operation pertains */ + unsigned int device_id; + int type; /* 0 = fd; 1 = trans */ + tbus fd; /* file descriptor over which to send reply */ + struct trans * trans; /* trans channel (to be used instead of "fd" if type == 1) */ + DWORD CompletionId; /* the CompletionId of the RDP request corresponding to the original operation */ + DWORD opcode; /* the rdpfs (or rdpport, rdpprinter, rdpsc) opcode of the original operation */ +// int length; /* length of "userdata", in bytes */ +// int FileId; /* file handle specified by the client */ + int uniqid; /* specified by the filesystem handler per transaction */ + NTSTATUS IoStatus; /* indicates success or error code returned by the filesystem operation, if any */ + int buflen; /* size (in bytes) of the reply data buffer */ + uint32_t flags; + uint8_t cmd; + uint32_t mask; + char fname[512]; + uint64_t actime; + uint64_t modtime; + tc_t mutex; + tc_t cv; +// pthread_mutex_t mutex; +// pthread_cond_t cv; + + #define RDPFS_CB_MAGIC 0xcdbea459 + uint32_t magic; + + int seq; + int idx; + int val; + + + /* a pointer to the actual function to be called: */ + void (*func)(void *, int, tbus, struct trans *, DWORD, DWORD, int, BYTE *); + int (*setData)(struct _callback *, int, const BYTE *); + int (*setFunc)(struct _callback *, void (*)(void *, int, tbus, struct trans *, DWORD, DWORD, int, BYTE *)); +// int (*call)(struct _callback *); + void * (*call)(void *); + int (*callData)(struct _callback *, int, const BYTE *); + + BYTE * userdata; /* optional extra data */ + + #define CBFLAG_NONE 0x00000000 /* no flags are set */ + #define CBFLAG_FINAL 0x00000001 /* the reply corresponds to the final (or only) step in a series */ + #define CBFLAG_INTERMEDIATE 0x00000002 /* the reply corresponds to an intermediate step in a series (rather than the final step) */ + #define CBFLAG_USERDATA 0x00000004 /* the userdata buffer contains data */ + #define CBFLAG_IOSTATUS 0x00000008 /* the IoStatus field is set */ + #define CBFLAG_FUNC 0x00000010 /* the "func" field points to a valid callback function that should be invoked */ + #define CBFLAG_IRQ 0x00000020 /* the current step is part of a pseudo-interrupt routine */ + #define CBFLAG_MUTEX 0x00000040 /* the mutex field should be handled appropriately */ + #define CBFLAG_SUPPRESS 0x00000080 /* do not transmit a reply message */ + #define CBFLAG_CMD 0x00000100 /* the cmd field indicates the IOCTL command */ + #define CBFLAG_MASK 0x00000200 /* the mask field contains a bitmask */ + #define CBFLAG_FS 0x01000000 /* the reply corresponds to a redirected filesystem operation */ + #define CBFLAG_PORT 0x02000000 /* the reply corresponds to a redirected serial port or paralle port operation */ + #define CBFLAG_SC 0x04000000 /* the reply corresponds to a redirected smartcard operation */ + #define CBFLAG_PRINT 0x08000000 /* the reply corresponds to a redirected printer operation */ +} callback; + +/*****************************************************************************/ +typedef uint64_t FILE_ALLOCATION_INFORMATION; + +typedef struct _RDP_FILE_RENAME_INFORMATION { + BYTE ReplaceIfExists; + BYTE RootDirectory; + DWORD FileNameLength; + BYTE * FileName; +} RDP_FILE_RENAME_INFORMATION; + +typedef struct _FILE_FS_ATTRIBUTE_INFORMATION { + DWORD FileSystemAttributes; + DWORD MaximumComponentNameLength; + DWORD FileSystemNameLength; + BYTE FileSystemName[512]; + + #define FILE_SUPPORTS_TRANSACTIONS 0x00200000 + #define FILE_SEQUENTIAL_WRITE_ONCE 0x00100000 + #define FILE_READ_ONLY_VOLUME 0x00080000 + #define FILE_NAMED_STREAMS 0x00040000 + #define FILE_SUPPORTS_ENCRYPTION 0x00020000 + #define FILE_SUPPORTS_OBJECT_IDS 0x00010000 + #define FILE_VOLUME_IS_COMPRESSED 0x00008000 + #define FILE_SUPPORTS_REMOTE_STORAGE 0x00000100 + #define FILE_SUPPORTS_REPARSE_POINTS 0x00000080 + #define FILE_SUPPORTS_SPARSE_FILES 0x00000040 + #define FILE_VOLUME_QUOTAS 0x00000020 + #define FILE_FILE_COMPRESSION 0x00000010 + #define FILE_PERSISTENT_ACLS 0x00000008 + #define FILE_UNICODE_ON_DISK 0x00000004 + #define FILE_CASE_PRESERVED_NAMES 0x00000002 + #define FILE_CASE_SENSITIVE_SEARCH 0x00000001 +} FILE_FS_ATTRIBUTE_INFORMATION; + +typedef struct _FILE_FS_CONTROL_INFORMATION { + QWORD FreeSpaceStartFiltering; + QWORD FreeSpaceThreshold; + QWORD FreeSpaceStopFiltering; + QWORD DefaultQuotaThreshold; + QWORD DefaultQuotaLimit; + DWORD FileSystemControlFlags; + + #define FILE_VC_CONTENT_INDEX_DISABLED 0x00000008 + #define FILE_VC_LOG_QUOTA_LIMIT 0x00000020 + #define FILE_VC_LOG_QUOTA_THRESHOLD 0x00000010 + #define FILE_VC_LOG_VOLUME_LIMIT 0x00000080 + #define FILE_VC_LOG_VOLUME_THRESHOLD 0x00000040 + #define FILE_VC_QUOTA_ENFORCE 0x00000002 + #define FILE_VC_QUOTA_TRACK 0x00000001 + #define FILE_VC_QUOTAS_INCOMPLETE 0x00000100 + #define FILE_VC_QUOTAS_REBUILDING 0x00000200 +} FILE_FS_CONTROL_INFORMATION; + +typedef struct _FILE_FS_LABEL_INFORMATION { + DWORD VolumeLabelLength; + BYTE * VolumeLabel; +} FILE_FS_LABEL_INFORMATION; + +typedef struct _FILE_FS_FULL_SIZE_INFORMATION { + QWORD TotalAllocationUnits; + QWORD CallerAvailableAllocationUnits; + QWORD ActualAvailableAllocationUnits; + DWORD SectorsPerAllocationUnit; + DWORD BytesPerSector; +} FILE_FS_FULL_SIZE_INFORMATION; + +typedef struct _FILE_FS_SIZE_INFORMATION { + QWORD TotalAllocationUnits; + QWORD ActualAvailableAllocationUnits; + DWORD SectorsPerAllocationUnit; + DWORD BytesPerSector; +} FILE_FS_SIZE_INFORMATION; + +typedef struct _FILE_FS_DEVICE_INFORMATION { + DWORD DeviceType; + DWORD Characteristics; + + #define FILE_REMOVABLE_MEDIA 0x00000001 + #define FILE_READ_ONLY_DEVICE 0x00000002 + #define FILE_FLOPPY_DISKETTE 0x00000004 + #define FILE_WRITE_ONCE_MEDIA 0x00000008 + #define FILE_REMOTE_DEVICE 0x00000010 + #define FILE_DEVICE_IS_MOUNTED 0x00000020 + #define FILE_VIRTUAL_VOLUME 0x00000040 + #define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080 + #define FILE_DEVICE_SECURE_OPEN 0x00000100 + #define FILE_CHARACTERISTIC_PNP_DEVICE 0x00000800 + #define FILE_CHARACTERISTIC_TS_DEVICE 0x00001000 + #define FILE_CHARACTERISTIC_WEBDAV_DEVICE 0x00002000 + + #define FILE_DEVICE_BEEP 0x00000001 + #define FILE_DEVICE_CD_ROM 0x00000002 + #define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003 + #define FILE_DEVICE_CONTROLLER 0x00000004 + #define FILE_DEVICE_DATALINK 0x00000005 + #define FILE_DEVICE_DFS 0x00000006 + #define FILE_DEVICE_DISK 0x00000007 + #define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008 + #define FILE_DEVICE_FILE_SYSTEM 0x00000009 + #define FILE_DEVICE_INPORT_PORT 0x0000000a + #define FILE_DEVICE_KEYBOARD 0x0000000b + #define FILE_DEVICE_MAILSLOT 0x0000000c + #define FILE_DEVICE_MIDI_IN 0x0000000d + #define FILE_DEVICE_MIDI_OUT 0x0000000e + #define FILE_DEVICE_MOUSE 0x0000000f + #define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010 + #define FILE_DEVICE_NAMED_PIPE 0x00000011 + #define FILE_DEVICE_NETWORK 0x00000012 + #define FILE_DEVICE_NETWORK_BROWSER 0x00000013 + #define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014 + #define FILE_DEVICE_NULL 0x00000015 + #define FILE_DEVICE_PARALLEL_PORT 0x00000016 + #define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017 + #define FILE_DEVICE_PRINTER 0x00000018 + #define FILE_DEVICE_SCANNER 0x00000019 + #define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a + #define FILE_DEVICE_SERIAL_PORT 0x0000001b + #define FILE_DEVICE_SCREEN 0x0000001c + #define FILE_DEVICE_SOUND 0x0000001d + #define FILE_DEVICE_STREAMS 0x0000001e + #define FILE_DEVICE_TAPE 0x0000001f + #define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020 + #define FILE_DEVICE_TRANSPORT 0x00000021 + #define FILE_DEVICE_UNKNOWN 0x00000022 + #define FILE_DEVICE_VIDEO 0x00000023 + #define FILE_DEVICE_VIRTUAL_DISK 0x00000024 + #define FILE_DEVICE_WAVE_IN 0x00000025 + #define FILE_DEVICE_WAVE_OUT 0x00000026 + #define FILE_DEVICE_8042_PORT 0x00000027 + #define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028 + #define FILE_DEVICE_BATTERY 0x00000029 + #define FILE_DEVICE_BUS_EXTENDER 0x0000002a + #define FILE_DEVICE_MODEM 0x0000002b + #define FILE_DEVICE_VDM 0x0000002c + #define FILE_DEVICE_MASS_STORAGE 0x0000002d + #define FILE_DEVICE_SMB 0x0000002e + #define FILE_DEVICE_KS 0x0000002f + #define FILE_DEVICE_CHANGER 0x00000030 + #define FILE_DEVICE_SMARTCARD 0x00000031 + #define FILE_DEVICE_ACPI 0x00000032 + #define FILE_DEVICE_DVD 0x00000033 + #define FILE_DEVICE_FULLSCREEN_VIDEO 0x00000034 + #define FILE_DEVICE_DFS_FILE_SYSTEM 0x00000035 + #define FILE_DEVICE_DFS_VOLUME 0x00000036 + #define FILE_DEVICE_SERENUM 0x00000037 + #define FILE_DEVICE_TERMSRV 0x00000038 + #define FILE_DEVICE_KSEC 0x00000039 + +} FILE_FS_DEVICE_INFORMATION; + +typedef struct _FILE_FS_DRIVER_PATH_INFORMATION { + BYTE DriverInPath; + union _Reserved { + BYTE bytes[3]; + DWORD uint24:24; + } Reserved; + DWORD DriverNameLength; + BYTE * DriverName; +} FILE_FS_DRIVER_PATH_INFORMATION; + +typedef struct _FILE_FS_VOLUME_INFORMATION { + QWORD VolumeCreationTime; + DWORD VolumeSerialNumber; + DWORD VolumeLabelLength; + BYTE SupportsObjects; + BYTE Reserved; + BYTE * VolumeLabel; +} FILE_FS_VOLUME_INFORMATION; + +typedef struct _FILE_DIRECTORY_INFORMATION { + DWORD NextEntryOffset; + DWORD FileIndex; + QWORD CreationTime; + QWORD LastAccessTime; + QWORD LastWriteTime; + QWORD ChangeTime; + QWORD EndOfFile; + QWORD AllocationSize; + DWORD FileAttributes; + DWORD FileNameLength; + BYTE * FileName; +} FILE_DIRECTORY_INFORMATION; + +typedef struct _FILE_FULL_DIR_INFORMATION { + DWORD NextEntryOffset; + DWORD FileIndex; + QWORD CreationTime; + QWORD LastAccessTime; + QWORD LastWriteTime; + QWORD ChangeTime; + QWORD EndOfFile; + QWORD AllocationSize; + DWORD FileAttributes; + DWORD FileNameLength; + DWORD EaSize; + BYTE * FileName; +} FILE_FULL_DIR_INFORMATION; + +typedef struct _FILE_FULL_EA_INFORMATION { + DWORD NextEntryOffset; + BYTE Flags; + BYTE EaNameLength; + WORD EaValueLength; + BYTE * EaName; + BYTE * EaValue; + + #define FILE_NEED_EA 0x00000080 +} FILE_FULL_EA_INFORMATION; + +typedef struct _FILE_GET_EA_INFORMATION { + DWORD NextEntryOffset; + BYTE EaNameLength; + BYTE * EaName; +} FILE_GET_EA_INFORMATION, FILE_SET_EA_INFORMATION; + +typedef struct _FILE_ID_BOTH_DIR_INFORMATION { + DWORD NextEntryOffset; + DWORD FileIndex; + QWORD CreationTime; + QWORD LastAccessTime; + QWORD LastWriteTime; + QWORD ChangeTime; + QWORD EndOfFile; + QWORD AllocationSize; + DWORD FileAttributes; + DWORD FileNameLength; + DWORD EaSize; + BYTE ShortNameLength; + BYTE Reserved1; + BYTE ShortName[24]; + WORD Reserved2; + QWORD FileId; + BYTE * FileName; +} FILE_ID_BOTH_DIR_INFORMATION; + +typedef struct _FILE_ID_FULL_DIR_INFORMATION { + DWORD NextEntryOffset; + DWORD FileIndex; + QWORD CreationTime; + QWORD LastAccessTime; + QWORD LastWriteTime; + QWORD ChangeTime; + QWORD EndOfFile; + QWORD AllocationSize; + DWORD FileAttributes; + DWORD FileNameLength; + DWORD EaSize; + DWORD Reserved; + QWORD FileId; + BYTE * FileName; +} FILE_ID_FULL_DIR_INFORMATION; + +typedef struct _FILE_NAME_INFORMATION { + DWORD FileNameLength; + BYTE FileName[1024]; +} FILE_NAME_INFORMATION; + +typedef struct _FILE_NAMES_INFORMATION { + DWORD NextEntryOffset; + DWORD FileIndex; + DWORD FileNameLength; + BYTE * FileName; +} FILE_NAMES_INFORMATION; + +typedef struct _FILE_RENAME_INFORMATION_V1 { + BYTE ReplaceIfExists; + BYTE Reserved[3]; + DWORD RootDirectory; + DWORD FileNameLength; + BYTE * FileName; +} FILE_RENAME_INFORMATION_V1; + +typedef struct _FILE_RENAME_INFORMATION { + BYTE ReplaceIfExists; + BYTE Reserved[7]; + QWORD RootDirectory; + DWORD FileNameLength; + BYTE * FileName; +} FILE_RENAME_INFORMATION; + +typedef struct _FILE_BASIC_INFORMATION { + QWORD CreationTime; + QWORD LastAccessTime; + QWORD LastWriteTime; + QWORD ChangeTime; + DWORD FileAttributes; + DWORD Reserved; +} FILE_BASIC_INFORMATION; + +typedef struct _FILE_BOTH_DIR_INFORMATION { + DWORD NextEntryOffset; + DWORD FileIndex; + QWORD CreationTime; + QWORD LastAccessTime; + QWORD LastWriteTime; + QWORD ChangeTime; + QWORD EndOfFile; + QWORD AllocationSize; + DWORD FileAttributes; + DWORD FileNameLength; + DWORD EaSize; + BYTE ShortNameLength; + BYTE Reserved; + BYTE ShortName[24]; + BYTE FileName[1024]; +} FILE_BOTH_DIR_INFORMATION; + +typedef struct _FILE_STANDARD_INFORMATION { + QWORD AllocationSize; + QWORD EndOfFile; + DWORD NumberOfLinks; + BYTE DeletePending; + BYTE Directory; + WORD Reserved; +} FILE_STANDARD_INFORMATION; + +typedef struct _FILE_ALL_INFORMATION { + FILE_BASIC_INFORMATION BasicInformation; + FILE_STANDARD_INFORMATION StandardInformation; + QWORD InternalInformation; + DWORD EaInformation; + DWORD AccessInformation; + QWORD PositionInformation; + DWORD ModeInformation; + DWORD AlignmentInformation; + FILE_NAME_INFORMATION NameInformation; + + #define FILE_BYTE_ALIGNMENT 0x00000000 + #define FILE_WORD_ALIGNMENT 0x00000001 + #define FILE_LONG_ALIGNMENT 0x00000003 + #define FILE_QUAD_ALIGNMENT 0x00000007 + #define FILE_OCTA_ALIGNMENT 0x0000000f + #define FILE_32_BYTE_ALIGNMENT 0x0000001f + #define FILE_64_BYTE_ALIGNMENT 0x0000003f + #define FILE_128_BYTE_ALIGNMENT 0x0000007f + #define FILE_256_BYTE_ALIGNMENT 0x000000ff + #define FILE_512_BYTE_ALIGNMENT 0x000001ff +} FILE_ALL_INFORMATION; + +typedef struct _FILE_ATTRIBUTE_TAG_INFORMATION { + DWORD FileAttributes; + DWORD ReparseTag; +} FILE_ATTRIBUTE_TAG_INFORMATION; + +/***/ + +typedef struct _RDPDR_HEADER { + WORD Component; + WORD PacketId; + void (*__destructor)(struct _RDPDR_HEADER *); + int (*out)(struct _RDPDR_HEADER *, struct stream *); + int (*in)(struct _RDPDR_HEADER *, struct stream *); + + #define RDPDR_CTYP_CORE 0x4472 + #define RDPDR_CTYP_PRN 0x5052 + #define PAKID_CORE_SERVER_ANNOUNCE 0x496E + #define PAKID_CORE_CLIENTID_CONFIRM 0x4343 + #define PAKID_CORE_CLIENT_NAME 0x434E + #define PAKID_CORE_DEVICELIST_ANNOUNCE 0x4441 + #define PAKID_CORE_DEVICE_REPLY 0x6472 + #define PAKID_CORE_DEVICE_IOREQUEST 0x4952 + #define PAKID_CORE_DEVICE_IOCOMPLETION 0x4943 + #define PAKID_CORE_SERVER_CAPABILITY 0x5350 + #define PAKID_CORE_CLIENT_CAPABILITY 0x4350 + #define PAKID_CORE_DEVICELIST_REMOVE 0x444D + #define PAKID_PRN_CACHE_DATA 0x5043 + #define PAKID_CORE_USER_LOGGEDON 0x554C + #define PAKID_PRN_USING_XPS 0x5543 +} RDPDR_HEADER; + +typedef struct _CAPABILITY_HEADER { + WORD CapabilityType; + WORD CapabilityLength; + DWORD Version; + void (*__destructor)(struct _CAPABILITY_HEADER *); + int (*out)(struct _CAPABILITY_HEADER *, struct stream *); + int (*in)(struct _CAPABILITY_HEADER *, struct stream *); + + #define CAP_GENERAL_TYPE 0x0001 + #define CAP_PRINTER_TYPE 0x0002 + #define CAP_PORT_TYPE 0x0003 + #define CAP_DRIVE_TYPE 0x0004 + #define CAP_SMARTCARD_TYPE 0x0005 + + #define GENERAL_CAPABILITY_VERSION_01 0x00000001 + #define GENERAL_CAPABILITY_VERSION_02 0x00000002 + #define PRINT_CAPABILITY_VERSION_01 0x00000001 + #define PORT_CAPABILITY_VERSION_01 0x00000001 + #define DRIVE_CAPABILITY_VERSION_01 0x00000001 + #define DRIVE_CAPABILITY_VERSION_02 0x00000002 + #define SMARTCARD_CAPABILITY_VERSION_01 0x00000001 +} CAPABILITY_HEADER; + +typedef struct _CAPABILITY_SET { + CAPABILITY_HEADER Header; + BYTE * capabilityData; + void (*__destructor)(struct _CAPABILITY_SET *); + int (*out)(struct _CAPABILITY_SET *, struct stream *); + int (*in)(struct _CAPABILITY_SET *, struct stream *); +} CAPABILITY_SET; + +typedef struct _DEVICE_ANNOUNCE { + DWORD DeviceType; + DWORD DeviceId; + BYTE PreferredDosName[8]; + DWORD DeviceDataLength; + BYTE * DeviceData; + void * item; + void (*__destructor)(struct _DEVICE_ANNOUNCE *); + int (*out)(struct _DEVICE_ANNOUNCE *, struct stream *); + int (*in)(struct _DEVICE_ANNOUNCE *, struct stream *); +} DEVICE_ANNOUNCE; + +typedef struct _DEVICE_ANNOUNCE_STATIC { + DWORD DeviceType; + DWORD DeviceId; + BYTE PreferredDosName[8]; + DWORD DeviceDataLength; + BYTE DeviceData[2048]; + void * item; + void (*__destructor)(struct _DEVICE_ANNOUNCE *); + int (*out)(struct _DEVICE_ANNOUNCE *, struct stream *); + int (*in)(struct _DEVICE_ANNOUNCE *, struct stream *); +} DEVICE_ANNOUNCE_STATIC; + +typedef struct _DR_DEVICE_IOREQUEST { + struct _RDPDR_HEADER Header; + DWORD DeviceId; + DWORD FileId; + DWORD CompletionId; + DWORD MajorFunction; + DWORD MinorFunction; + void (*__destructor)(struct _DR_DEVICE_IOREQUEST *); + int (*out)(struct _DR_DEVICE_IOREQUEST *, struct stream *); + int (*in)(struct _DR_DEVICE_IOREQUEST *, struct stream *); + + // + // Standard IRP Major codes + // + #define IRP_MJ_CREATE 0x00 + #define IRP_MJ_CREATE_NAMED_PIPE 0x01 + #define IRP_MJ_CLOSE 0x02 + #define IRP_MJ_READ 0x03 + #define IRP_MJ_WRITE 0x04 + #define IRP_MJ_QUERY_INFORMATION 0x05 + #define IRP_MJ_SET_INFORMATION 0x06 + #define IRP_MJ_QUERY_EA 0x07 + #define IRP_MJ_SET_EA 0x08 + #define IRP_MJ_FLUSH_BUFFERS 0x09 + #define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a + #define IRP_MJ_SET_VOLUME_INFORMATION 0x0b + #define IRP_MJ_DIRECTORY_CONTROL 0x0c + #define IRP_MJ_QUERY_DIRECTORY 0x0c + #define IRP_MJ_FILE_SYSTEM_CONTROL 0x0d + #define IRP_MJ_DEVICE_CONTROL 0x0e + #define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0f + #define IRP_MJ_SHUTDOWN 0x10 + #define IRP_MJ_LOCK_CONTROL 0x11 + #define IRP_MJ_CLEANUP 0x12 + #define IRP_MJ_CREATE_MAILSLOT 0x13 + #define IRP_MJ_QUERY_SECURITY 0x14 + #define IRP_MJ_SET_SECURITY 0x15 + #define IRP_MJ_POWER 0x16 + #define IRP_MJ_SYSTEM_CONTROL 0x17 + #define IRP_MJ_DEVICE_CHANGE 0x18 + #define IRP_MJ_QUERY_QUOTA 0x19 + #define IRP_MJ_SET_QUOTA 0x1a + #define IRP_MJ_PNP 0x1b + #define IRP_MJ_MAXIMUM_FUNCTION 0x1b + + // + // IRP minor codes + // + #define IRP_MN_QUERY_DIRECTORY 0x01 + #define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x02 + #define IRP_MN_USER_FS_REQUEST 0x00 + #define IRP_MN_MOUNT_VOLUME 0x01 + #define IRP_MN_VERIFY_VOLUME 0x02 + #define IRP_MN_LOAD_FILE_SYSTEM 0x03 + #define IRP_MN_TRACK_LINK 0x04 + #define IRP_MN_LOCK 0x01 + #define IRP_MN_UNLOCK_SINGLE 0x02 + #define IRP_MN_UNLOCK_ALL 0x03 + #define IRP_MN_UNLOCK_ALL_BY_KEY 0x04 + #define IRP_MN_NORMAL 0x00 + #define IRP_MN_DPC 0x01 + #define IRP_MN_MDL 0x02 + #define IRP_MN_COMPLETE 0x04 + #define IRP_MN_COMPRESSED 0x08 + #define IRP_MN_MDL_DPC (IRP_MN_MDL | IRP_MN_DPC) + #define IRP_MN_COMPLETE_MDL (IRP_MN_COMPLETE | IRP_MN_MDL) + #define IRP_MN_COMPLETE_MDL_DPC (IRP_MN_COMPLETE_MDL | IRP_MN_DPC) + #define IRP_MN_SCSI_CLASS 0x01 + #define IRP_MN_START_DEVICE 0x00 + #define IRP_MN_QUERY_REMOVE_DEVICE 0x01 + #define IRP_MN_REMOVE_DEVICE 0x02 + #define IRP_MN_CANCEL_REMOVE_DEVICE 0x03 + #define IRP_MN_STOP_DEVICE 0x04 + #define IRP_MN_QUERY_STOP_DEVICE 0x05 + #define IRP_MN_CANCEL_STOP_DEVICE 0x06 + #define IRP_MN_QUERY_DEVICE_RELATIONS 0x07 + #define IRP_MN_QUERY_INTERFACE 0x08 + #define IRP_MN_QUERY_CAPABILITIES 0x09 + #define IRP_MN_QUERY_RESOURCES 0x0A + #define IRP_MN_QUERY_RESOURCE_REQUIREMENTS 0x0B + #define IRP_MN_QUERY_DEVICE_TEXT 0x0C + #define IRP_MN_FILTER_RESOURCE_REQUIREMENTS 0x0D + #define IRP_MN_READ_CONFIG 0x0F + #define IRP_MN_WRITE_CONFIG 0x10 + #define IRP_MN_EJECT 0x11 + #define IRP_MN_SET_LOCK 0x12 + #define IRP_MN_QUERY_ID 0x13 + #define IRP_MN_QUERY_PNP_DEVICE_STATE 0x14 + #define IRP_MN_QUERY_BUS_INFORMATION 0x15 + #define IRP_MN_DEVICE_USAGE_NOTIFICATION 0x16 + #define IRP_MN_SURPRISE_REMOVAL 0x17 + #define IRP_MN_QUERY_LEGACY_BUS_INFORMATION 0x18 + #define IRP_MN_WAIT_WAKE 0x00 + #define IRP_MN_POWER_SEQUENCE 0x01 + #define IRP_MN_SET_POWER 0x02 + #define IRP_MN_QUERY_POWER 0x03 + #define IRP_MN_QUERY_ALL_DATA 0x00 + #define IRP_MN_QUERY_SINGLE_INSTANCE 0x01 + #define IRP_MN_CHANGE_SINGLE_INSTANCE 0x02 + #define IRP_MN_CHANGE_SINGLE_ITEM 0x03 + #define IRP_MN_ENABLE_EVENTS 0x04 + #define IRP_MN_DISABLE_EVENTS 0x05 + #define IRP_MN_ENABLE_COLLECTION 0x06 + #define IRP_MN_DISABLE_COLLECTION 0x07 + #define IRP_MN_REGINFO 0x08 + #define IRP_MN_EXECUTE_METHOD 0x09 + +} DR_DEVICE_IOREQUEST; + +typedef struct _DR_CREATE_REQ { + DR_DEVICE_IOREQUEST DeviceIoRequest; + DWORD DesiredAccess; + QWORD AllocationSize; + DWORD FileAttributes; + DWORD SharedAccess; + DWORD CreateDisposition; + DWORD CreateOptions; + DWORD PathLength; + BYTE Path[512]; + void (*__destructor)(struct _DR_CREATE_REQ *); + int (*out)(struct _DR_CREATE_REQ *, struct stream *); + int (*in)(struct _DR_CREATE_REQ *, struct stream *); + + /* For "File_Pipe_Printer_Access_Mask" (4 bytes) */ + #define FILE_READ_DATA 0x00000001 + #define FILE_WRITE_DATA 0x00000002 + #define FILE_APPEND_DATA 0x00000004 + #define FILE_READ_EA 0x00000008 + #define FILE_WRITE_EA 0x00000010 + #define FILE_EXECUTE 0x00000020 + #define FILE_READ_ATTRIBUTES 0x00000080 + #define FILE_WRITE_ATTRIBUTES 0x00000100 + #define DELETE 0x00010000 + #define READ_CONTROL 0x00020000 + #define WRITE_DAC 0x00040000 + #define WRITE_OWNER 0x00080000 + #define SYNCHRONIZE 0x00100000 + #define ACCESS_SYSTEM_SECURITY 0x01000000 + #define MAXIMUM_ALLOWED 0x02000000 + #define GENERIC_ALL 0x10000000 + #define GENERIC_EXECUTE 0x20000000 + #define GENERIC_WRITE 0x40000000 + #define GENERIC_READ 0x80000000 + + /* For "directory_access_mask" (4 bytes) */ + #define FILE_LIST_DIRECTORY 0x00000001 + #define FILE_ADD_FILE 0x00000002 + #define FILE_ADD_SUBDIRECTORY 0x00000004 + #define FILE_TRAVERSE 0x00000020 + #define FILE_DELETE_CHILD 0x00000040 + + /* File attributes */ + #define FILE_ATTRIBUTE_ARCHIVE 0x00000020 + #define FILE_ATTRIBUTE_COMPRESSED 0x00000800 + #define FILE_ATTRIBUTE_DIRECTORY 0x00000010 + #define FILE_ATTRIBUTE_ENCRYPTED 0x00004000 + #define FILE_ATTRIBUTE_HIDDEN 0x00000002 + #define FILE_ATTRIBUTE_NORMAL 0x00000080 + #define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000 + #define FILE_ATTRIBUTE_OFFLINE 0x00001000 + #define FILE_ATTRIBUTE_READONLY 0x00000001 + #define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400 + #define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200 + #define FILE_ATTRIBUTE_SYSTEM 0x00000004 + #define FILE_ATTRIBUTE_TEMPORARY 0x00000100 + + /* Shared access */ + #define FILE_SHARE_READ 0x00000001 + #define FILE_SHARE_WRITE 0x00000002 + #define FILE_SHARE_DELETE 0x00000004 + + /* Dispositions */ + #define FILE_OPEN 0x00000001 + #define FILE_CREATE 0x00000002 + #define FILE_OPEN_IF 0x00000003 + #define FILE_OVERWRITE 0x00000004 + #define FILE_OVERWRITE_IF 0x00000005 + + /* Create options */ + #define FILE_DIRECTORY_FILE 0x00000001 + #define FILE_WRITE_THROUGH 0x00000002 + #define FILE_SEQUENTIAL_ONLY 0x00000004 + #define FILE_NO_INTERMEDIATE_BUFFERING 0x00000008 + #define FILE_SYNCHRONOUS_IO_ALERT 0x00000010 + #define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 + #define FILE_NON_DIRECTORY_FILE 0x00000040 + #define FILE_COMPLETE_IF_OPLOCKED 0x00000100 + #define FILE_NO_EA_KNOWLEDGE 0x00000200 + #define FILE_RANDOM_ACCESS 0x00000800 + #define FILE_DELETE_ON_CLOSE 0x00001000 + #define FILE_OPEN_BY_FILE_ID 0x00002000 + #define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000 + #define FILE_NO_COMPRESSION 0x00008000 + #define FILE_RESERVE_OPFILTER 0x00100000 + #define FILE_OPEN_REPARSE_POINT 0x00200000 + #define FILE_OPEN_NO_RECALL 0x00400000 + #define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000 + +} DR_CREATE_REQ, DR_PORT_CREATE_REQ; + +typedef struct _DR_CLOSE_REQ { + DR_DEVICE_IOREQUEST DeviceIoRequest; + BYTE Padding[32]; + void (*__destructor)(struct _DR_CLOSE_REQ *); + int (*in)(struct _DR_CLOSE_REQ *, struct stream *); + int (*out)(struct _DR_CLOSE_REQ *, struct stream *); +} DR_CLOSE_REQ; + +typedef struct _DR_READ_REQ { + DR_DEVICE_IOREQUEST DeviceIoRequest; + DWORD Length; + QWORD Offset; + BYTE Padding[20]; + void (*__destructor)(struct _DR_READ_REQ *); + int (*in)(struct _DR_READ_REQ *, struct stream *); + int (*out)(struct _DR_READ_REQ *, struct stream *); +} DR_READ_REQ, DR_PORT_READ_REQ; + +typedef struct _DR_WRITE_REQ { + DR_DEVICE_IOREQUEST DeviceIoRequest; + DWORD Length; + QWORD Offset; + BYTE Padding[20]; + BYTE * WriteData; + void (*__destructor)(struct _DR_WRITE_REQ *); + int (*in)(struct _DR_WRITE_REQ *, struct stream *); + int (*out)(struct _DR_WRITE_REQ *, struct stream *); +} DR_WRITE_REQ, DR_PORT_WRITE_REQ; + +typedef struct _DR_CONTROL_REQ { + DR_DEVICE_IOREQUEST DeviceIoRequest; + DWORD OutputBufferLength; + DWORD InputBufferLength; + DWORD IoControlCode; + BYTE Padding[20]; + BYTE * InputBuffer; + void (*__destructor)(struct _DR_CONTROL_REQ *); + int (*in)(struct _DR_CONTROL_REQ *, struct stream *); + int (*out)(struct _DR_CONTROL_REQ *, struct stream *); +} DR_CONTROL_REQ, DR_PORT_CONTROL_REQ; + +typedef struct _DR_DEVICE_IOCOMPLETION { + RDPDR_HEADER Header; + DWORD DeviceId; + DWORD CompletionId; + NTSTATUS IoStatus; + void (*__destructor)(struct _DR_DEVICE_IOCOMPLETION *); + int (*in)(struct _DR_DEVICE_IOCOMPLETION *, struct stream *); + int (*out)(struct _DR_DEVICE_IOCOMPLETION *, struct stream *); +} DEVICE_IOCOMPLETION, DR_DEVICE_IOCOMPLETION; + +typedef struct _DR_CREATE_RSP { + DR_DEVICE_IOCOMPLETION DeviceIoReply; + DWORD FileId; + BYTE Information; + void (*__destructor)(struct _DR_CREATE_RSP *); + int (*in)(struct _DR_CREATE_RSP *, struct stream *); + int (*out)(struct _DR_CREATE_RSP *, struct stream *); + + #define FILE_SUPERSEDED 0x00000000 + #define FILE_OPENED 0x00000001 + #define FILE_OVERWRITTEN 0x00000003 +} DR_CREATE_RSP, DR_PORT_CREATE_RSP; + +typedef struct _DR_CLOSE_RSP { + DR_DEVICE_IOCOMPLETION DeviceIoReply; + BYTE Padding[5]; + void (*__destructor)(struct _DR_CLOSE_RSP *); + int (*in)(struct _DR_CLOSE_RSP *, struct stream *); + int (*out)(struct _DR_CLOSE_RSP *, struct stream *); +} DR_CLOSE_RSP, DR_PORT_CLOSE_RSP; + +typedef struct _DR_READ_RSP { + DR_DEVICE_IOCOMPLETION DeviceIoReply; + DWORD Length; + BYTE * ReadData; + void (*__destructor)(struct _DR_READ_RSP *); + int (*in)(struct _DR_READ_RSP *, struct stream *); + int (*out)(struct _DR_READ_RSP *, struct stream *); +} DR_READ_RSP, DR_DRIVE_READ_RSP, DR_PORT_READ_RSP; + +typedef struct _DR_WRITE_RSP { + DR_DEVICE_IOCOMPLETION DeviceIoReply; + DWORD Length; + BYTE Padding; + void (*__destructor)(struct _DR_WRITE_RSP *); + int (*in)(struct _DR_WRITE_RSP *, struct stream *); + int (*out)(struct _DR_WRITE_RSP *, struct stream *); +} DR_WRITE_RSP, DR_DRIVE_WRITE_RSP, DR_PORT_WRITE_RSP; + +typedef struct _DR_CONTROL_RSP { + DR_DEVICE_IOCOMPLETION DeviceIoReply; + DWORD OutputBufferLength; + BYTE * OutputBuffer; + void (*__destructor)(struct _DR_CONTROL_RSP *); + int (*in)(struct _DR_CONTROL_RSP *, struct stream *); + int (*out)(struct _DR_CONTROL_RSP *, struct stream *); +} DR_CONTROL_RSP, DR_DRIVE_CONTROL_RSP, DR_PORT_CONTROL_RSP; + +typedef struct _RDP_LOCK_INFO { + QWORD Length; + QWORD Offset; + void (*__destructor)(struct _RDP_LOCK_INFO *); + int (*in)(struct _RDP_LOCK_INFO *, struct stream *); + int (*out)(struct _RDP_LOCK_INFO *, struct stream *); +} RDP_LOCK_INFO; + +typedef struct _DR_CORE_DEVICE_ANNOUNCE_RSP { + RDPDR_HEADER Header; + DWORD DeviceId; + DWORD ResultCode; + void (*__destructor)(struct _DR_CORE_DEVICE_ANNOUNCE_RSP *); + int (*in)(struct _DR_CORE_DEVICE_ANNOUNCE_RSP *, struct stream *); + int (*out)(struct _DR_CORE_DEVICE_ANNOUNCE_RSP *, struct stream *); +} DR_CORE_DEVICE_ANNOUNCE_RSP; + +typedef struct _DR_CORE_SERVER_ANNOUNCE_REQ { + RDPDR_HEADER Header; + WORD VersionMajor; /* must be set to 0x0001 */ + WORD VersionMinor; /* may be 0x000C (Vista, Windows 7, Server 2008), 0x000A (Server 2003 SP2), 0x0006 (XP SP3), 0x0005 (Windows XP, Windows XP SP1, Windows XP SP2, Windows Server 2003, and Windows Server 2003 with SP1), or 0x0002 (Windows 2000) */ + DWORD ClientId; + void (*__destructor)(struct _DR_CORE_SERVER_ANNOUNCE_REQ *); + int (*in)(struct _DR_CORE_SERVER_ANNOUNCE_REQ *, struct stream *); + int (*out)(struct _DR_CORE_SERVER_ANNOUNCE_REQ *, struct stream *); +} DR_CORE_SERVER_ANNOUNCE_REQ; + +typedef struct _DR_CORE_SERVER_ANNOUNCE_RSP { + RDPDR_HEADER Header; + WORD VersionMajor; /* must be set to 0x0001 */ + WORD VersionMinor; /* may be 0x000C (Vista, Windows 7, Server 2008), 0x000A (Server 2003 SP2), 0x0006 (XP SP3), 0x0005 (Windows XP, Windows XP SP1, Windows XP SP2, Windows Server 2003, and Windows Server 2003 with SP1), or 0x0002 (Windows 2000) */ + DWORD ClientId; + void (*__destructor)(struct _DR_CORE_SERVER_ANNOUNCE_RSP *); + int (*in)(struct _DR_CORE_SERVER_ANNOUNCE_RSP *, struct stream *); + int (*out)(struct _DR_CORE_SERVER_ANNOUNCE_RSP *, struct stream *); +} DR_CORE_SERVER_ANNOUNCE_RSP; + +typedef struct _DR_CORE_CLIENT_NAME_REQ { + RDPDR_HEADER Header; + DWORD UnicodeFlag; + DWORD CodePage; + DWORD ComputerNameLen; + BYTE * ComputerName; + void (*__destructor)(struct _DR_CORE_CLIENT_NAME_REQ *); + int (*in)(struct _DR_CORE_CLIENT_NAME_REQ *, struct stream *); + int (*out)(struct _DR_CORE_CLIENT_NAME_REQ *, struct stream *); +} DR_CORE_CLIENT_NAME_REQ; + +typedef struct _DR_CORE_USER_LOGGEDON { + RDPDR_HEADER Header; + void (*__destructor)(struct _DR_CORE_USER_LOGGEDON *); + int (*in)(struct _DR_CORE_USER_LOGGEDON *, struct stream *); + int (*out)(struct _DR_CORE_USER_LOGGEDON *, struct stream *); +} DR_CORE_USER_LOGGEDON; + +typedef struct _DR_CORE_SERVER_CLIENTID_CONFIRM { + RDPDR_HEADER Header; + WORD VersionMajor; /* must be set to 0x0001 */ + WORD VersionMinor; /* may be 0x000C (Vista, Windows 7, Server 2008), 0x000A (Server 2003 SP2), 0x0006 (XP SP3), 0x0005 (Windows XP, Windows XP SP1, Windows XP SP2, Windows Server 2003, and Windows Server 2003 with SP1), or 0x0002 (Windows 2000) */ + DWORD ClientId; + void (*__destructor)(struct _DR_CORE_SERVER_CLIENTID_CONFIRM *); + int (*in)(struct _DR_CORE_SERVER_CLIENTID_CONFIRM *, struct stream *); + int (*out)(struct _DR_CORE_SERVER_CLIENTID_CONFIRM *, struct stream *); +} DR_CORE_SERVER_CLIENTID_CONFIRM; + +typedef struct _DR_CORE_CAPABILITY_REQ { + RDPDR_HEADER Header; + WORD numCapabilities; + WORD Padding; + CAPABILITY_SET * CapabilityMessage; + void (*__destructor)(struct _DR_CORE_CAPABILITY_REQ *); + int (*out)(struct _DR_CORE_CAPABILITY_REQ *, struct stream *); + int (*in)(struct _DR_CORE_CAPABILITY_REQ *, struct stream *); +} DR_CORE_CAPABILITY_REQ, DR_CORE_CAPABILITY_RSP; + +typedef struct _GENERAL_CAPS_SET { + CAPABILITY_HEADER Header; + DWORD osType; + DWORD osVersion; + WORD protocolMajorVersion; + WORD protocolMinorVersion; + DWORD ioCode1; + DWORD ioCode2; + DWORD extendedPDU; + DWORD extraFlags1; + DWORD extraFlags2; + DWORD SpecialTypeDeviceCap; + void (*__destructor)(struct _GENERAL_CAPS_SET *); + int (*out)(struct _GENERAL_CAPS_SET *, struct stream *); + int (*in)(struct _GENERAL_CAPS_SET *, struct stream *); + + #define RDPDR_IRP_MJ_CREATE 0x00000001 + #define RDPDR_IRP_MJ_CLEANUP 0x00000002 + #define RDPDR_IRP_MJ_CLOSE 0x00000004 + #define RDPDR_IRP_MJ_READ 0x00000008 + #define RDPDR_IRP_MJ_WRITE 0x00000010 + #define RDPDR_IRP_MJ_FLUSH_BUFFERS 0x00000020 + #define RDPDR_IRP_MJ_SHUTDOWN 0x00000040 + #define RDPDR_IRP_MJ_DEVICE_CONTROL 0x00000080 + #define RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION 0x00000100 + #define RDPDR_IRP_MJ_SET_VOLUME_INFORMATION 0x00000200 + #define RDPDR_IRP_MJ_QUERY_INFORMATION 0x00000400 + #define RDPDR_IRP_MJ_SET_INFORMATION 0x00000800 + #define RDPDR_IRP_MJ_DIRECTORY_CONTROL 0x00001000 + #define RDPDR_IRP_MJ_LOCK_CONTROL 0x00002000 + #define RDPDR_IRP_MJ_QUERY_SECURITY 0x00004000 + #define RDPDR_IRP_MJ_SET_SECURITY 0x00008000 + + #define RDPDR_DEVICE_REMOVE_PDUS 0x00000001 + #define RDPDR_CLIENT_DISPLAY_NAME_PDU 0x00000002 + #define RDPDR_USER_LOGGEDON_PDU 0x00000004 + + #define ENABLE_ASYNCIO 0x00000001 +} GENERAL_CAPS_SET; + +typedef struct _PRINTER_CAPS_SET { + CAPABILITY_HEADER Header; + void (*__destructor)(struct _PRINTER_CAPS_SET *); + int (*out)(struct _PRINTER_CAPS_SET *, struct stream *); + int (*in)(struct _PRINTER_CAPS_SET *, struct stream *); +} PRINTER_CAPS_SET; + +typedef struct _PORT_CAPS_SET { + CAPABILITY_HEADER Header; + void (*__destructor)(struct _PORT_CAPS_SET *); + int (*out)(struct _PORT_CAPS_SET *, struct stream *); + int (*in)(struct _PORT_CAPS_SET *, struct stream *); +} PORT_CAPS_SET; + +typedef struct _DRIVE_CAPS_SET { + CAPABILITY_HEADER Header; + void (*__destructor)(struct _DRIVE_CAPS_SET *); + int (*out)(struct _DRIVE_CAPS_SET *, struct stream *); + int (*in)(struct _DRIVE_CAPS_SET *, struct stream *); +} DRIVE_CAPS_SET; + +typedef struct _SMARTCARD_CAPS_SET { + CAPABILITY_HEADER Header; + void (*__destructor)(struct _SMARTCARD_CAPS_SET *); + int (*out)(struct _SMARTCARD_CAPS_SET *, struct stream *); + int (*in)(struct _SMARTCARD_CAPS_SET *, struct stream *); +} SMARTCARD_CAPS_SET; + +typedef struct _DR_CORE_DEVICELIST_ANNOUNCE_REQ { + RDPDR_HEADER Header; + DWORD DeviceCount; + DEVICE_ANNOUNCE * DeviceList; + void (*__destructor)(struct _DR_CORE_DEVICELIST_ANNOUNCE_REQ *); + int (*out)(struct _DR_CORE_DEVICELIST_ANNOUNCE_REQ *, struct stream *); + int (*in)(struct _DR_CORE_DEVICELIST_ANNOUNCE_REQ *, struct stream *); +} DR_CORE_DEVICELIST_ANNOUNCE_REQ; + +typedef struct _DR_DEVICELIST_ANNOUNCE { + RDPDR_HEADER Header; + DWORD DeviceCount; + DEVICE_ANNOUNCE ** DeviceList; + void (*__destructor)(struct _DR_DEVICELIST_ANNOUNCE *); + int (*in)(struct _DR_DEVICELIST_ANNOUNCE *, struct stream *); + int (*out)(struct _DR_DEVICELIST_ANNOUNCE *, struct stream *); +} DR_DEVICELIST_ANNOUNCE; + +typedef struct _DR_DEVICELIST_ANNOUNCE_STATIC { + RDPDR_HEADER Header; + DWORD DeviceCount; + DEVICE_ANNOUNCE_STATIC DeviceList[96]; + void (*__destructor)(struct _DR_DEVICELIST_ANNOUNCE *); + int (*in)(struct _DR_DEVICELIST_ANNOUNCE *, struct stream *); + int (*out)(struct _DR_DEVICELIST_ANNOUNCE *, struct stream *); +} DR_DEVICELIST_ANNOUNCE_STATIC; + +typedef struct _DR_DEVICELIST_REMOVE { + RDPDR_HEADER Header; + DWORD DeviceCount; + DWORD * DeviceIds; + void (*__destructor)(struct _DR_DEVICELIST_REMOVE *); + int (*in)(struct _DR_DEVICELIST_REMOVE *, struct stream *); + int (*out)(struct _DR_DEVICELIST_REMOVE *, struct stream *); +} DR_DEVICELIST_REMOVE; + + +typedef struct _DR_DRIVE_CORE_DEVICE_IOREQUEST { + DR_DEVICE_IOREQUEST Header; + void (*__destructor)(struct _DR_DRIVE_CORE_DEVICE_IOREQUEST *); + int (*in)(struct _DR_DRIVE_CORE_DEVICE_IOREQUEST *, struct stream *); + int (*out)(struct _DR_DRIVE_CORE_DEVICE_IOREQUEST *, struct stream *); +} DR_DRIVE_CORE_DEVICE_IOREQUEST; + +typedef struct _DR_DRIVE_CREATE_REQ { + DR_CREATE_REQ DeviceCreateRequest; + void (*__destructor)(struct _DR_DRIVE_CREATE_REQ *); + int (*out)(struct _DR_DRIVE_CREATE_REQ *, struct stream *); + int (*in)(struct _DR_DRIVE_CREATE_REQ *, struct stream *); +} DR_DRIVE_CREATE_REQ; + +typedef struct _DR_DRIVE_CLOSE_REQ { + DR_CLOSE_REQ DeviceCloseRequest; + void (*__destructor)(struct _DR_DRIVE_CLOSE_REQ *); + int (*out)(struct _DR_DRIVE_CLOSE_REQ *, struct stream *); + int (*in)(struct _DR_DRIVE_CLOSE_REQ *, struct stream *); +} DR_DRIVE_CLOSE_REQ; + +typedef struct _DR_DRIVE_READ_REQ { + DR_READ_REQ DeviceReadRequest; + void (*__destructor)(struct _DR_DRIVE_READ_REQ *); + int (*out)(struct _DR_DRIVE_READ_REQ *, struct stream *); + int (*in)(struct _DR_DRIVE_READ_REQ *, struct stream *); +} DR_DRIVE_READ_REQ; + +typedef struct _DR_DRIVE_WRITE_REQ { + DR_WRITE_REQ DeviceWriteRequest; + void (*__destructor)(struct _DR_DRIVE_WRITE_REQ *); + int (*out)(struct _DR_DRIVE_WRITE_REQ *, struct stream *); + int (*in)(struct _DR_DRIVE_WRITE_REQ *, struct stream *); +} DR_DRIVE_WRITE_REQ; + +typedef struct _DR_DRIVE_CONTROL_REQ { + DR_CONTROL_REQ Header; + void (*__destructor)(struct _DR_DRIVE_CONTROL_REQ *); + int (*out)(struct _DR_DRIVE_CONTROL_REQ *, struct stream *); + int (*in)(struct _DR_DRIVE_CONTROL_REQ *, struct stream *); + + #define FSCTL_CREATE_OR_GET_OBJECT_ID 0x900c0 + #define FSCTL_DELETE_OBJECT_ID 0x900a0 + #define FSCTL_DELETE_REPARSE_POINT 0x900ac + #define FSCTL_FILESYSTEM_GET_STATISTICS 0x90060 + #define FSCTL_FIND_FILES_BY_SID 0x9008f + #define FSCTL_GET_COMPRESSION 0x9003c + #define FSCTL_GET_NTFS_VOLUME_DATA 0x90064 + #define FSCTL_GET_OBJECT_ID 0x9009c + #define FSCTL_GET_REPARSE_POINT 0x900a8 + #define FSCTL_GET_RETRIEVAL_POINTERS 0x90073 + #define FSCTL_IS_PATHNAME_VALID 0x9002c + #define FSCTL_LMR_GET_LINK_TRACKING_INFORMATION 0x1400e8 + #define FSCTL_LMR_SET_LINK_TRACKING_INFORMATION 0x1400ec + #define FSCTL_PIPE_TRANSCEIVE 0x11c017 + #define FSCTL_PIPE_WAIT 0x110018 + #define FSCTL_QUERY_ALLOCATED_RANGES 0x940cf + #define FSCTL_READ_FILE_USN_DATA 0x900eb + #define FSCTL_RECALL_FILE 0x90117 + #define FSCTL_SET_COMPRESSION 0x9c040 + #define FSCTL_SET_ENCRYPTION 0x900D7 + #define FSCTL_SET_OBJECT_ID 0x90098 + #define FSCTL_SET_OBJECT_ID_EXTENDED 0x900bc + #define FSCTL_SET_REPARSE_POINT 0x900a4 + #define FSCTL_SET_SHORT_NAME_BEHAVIOR 0x901B4 + #define FSCTL_SET_SPARSE 0x900c4 + #define FSCTL_SET_ZERO_DATA 0x980c8 + #define FSCTL_SET_ZERO_ON_DEALLOCATION 0x90194 + #define FSCTL_SIS_COPYFILE 0x90100 + #define FSCTL_WRITE_USN_CLOSE_RECORD 0x900ef + +#ifndef NT_IOCTLS +#define NT_IOCTLS + + #define IOCTL_SERIAL_SET_BAUD_RATE 0x001B0004 + #define IOCTL_SERIAL_GET_BAUD_RATE 0x001B0050 + #define IOCTL_SERIAL_SET_LINE_CONTROL 0x001B000C + #define IOCTL_SERIAL_GET_LINE_CONTROL 0x001B0054 + #define IOCTL_SERIAL_SET_TIMEOUTS 0x001B001C + #define IOCTL_SERIAL_GET_TIMEOUTS 0x001B0020 + #define IOCTL_SERIAL_SET_CHARS 0x001B0058 + #define IOCTL_SERIAL_GET_CHARS 0x001B005C + #define IOCTL_SERIAL_SET_DTR 0x001B0024 + #define IOCTL_SERIAL_CLR_DTR 0x001B0028 + #define IOCTL_SERIAL_RESET_DEVICE 0x001B002C + #define IOCTL_SERIAL_SET_RTS 0x001B0030 + #define IOCTL_SERIAL_CLR_RTS 0x001B0034 + #define IOCTL_SERIAL_SET_XOFF 0x001B0038 + #define IOCTL_SERIAL_SET_XON 0x001B003C + #define IOCTL_SERIAL_SET_BREAK_ON 0x001B0010 + #define IOCTL_SERIAL_SET_BREAK_OFF 0x001B0014 + #define IOCTL_SERIAL_SET_QUEUE_SIZE 0x001B0008 + #define IOCTL_SERIAL_GET_WAIT_MASK 0x001B0040 + #define IOCTL_SERIAL_SET_WAIT_MASK 0x001B0044 + #define IOCTL_SERIAL_WAIT_ON_MASK 0x001B0048 + #define IOCTL_SERIAL_IMMEDIATE_CHAR 0x001B0018 + #define IOCTL_SERIAL_PURGE 0x001B004C + #define IOCTL_SERIAL_GET_HANDFLOW 0x001B0060 + #define IOCTL_SERIAL_SET_HANDFLOW 0x001B0064 + #define IOCTL_SERIAL_GET_MODEMSTATUS 0x001B0068 + #define IOCTL_SERIAL_GET_DTRRTS 0x001B0078 + #define IOCTL_SERIAL_GET_COMMSTATUS 0x001B0084 + #define IOCTL_SERIAL_GET_PROPERTIES 0x001B0074 + #define IOCTL_SERIAL_XOFF_COUNTER 0x001B0070 + #define IOCTL_SERIAL_LSRMST_INSERT 0x001B007C + #define IOCTL_SERIAL_CONFIG_SIZE 0x001B0080 + #define IOCTL_SERIAL_GET_STATS 0x001B008C + #define IOCTL_SERIAL_CLEAR_STATS 0x001B0090 + #define IOCTL_SERIAL_GET_MODEM_CONTROL 0x001B0094 + #define IOCTL_SERIAL_SET_MODEM_CONTROL 0x001B0098 + #define IOCTL_SERIAL_SET_FIFO_CONTROL 0x001B009C + #define IOCTL_PAR_QUERY_INFORMATION 0x00160004 + #define IOCTL_PAR_SET_INFORMATION 0x00160008 + #define IOCTL_PAR_QUERY_DEVICE_ID 0x0016000C + #define IOCTL_PAR_QUERY_DEVICE_ID_SIZE 0x00160010 + #define IOCTL_IEEE1284_GET_MODE 0x00160014 + #define IOCTL_IEEE1284_NEGOTIATE 0x00160018 + #define IOCTL_PAR_SET_WRITE_ADDRESS 0x0016001C + #define IOCTL_PAR_SET_READ_ADDRESS 0x00160020 + #define IOCTL_PAR_GET_DEVICE_CAPS 0x00160024 + #define IOCTL_PAR_GET_DEFAULT_MODES 0x00160028 + #define IOCTL_PAR_QUERY_RAW_DEVICE_ID 0x00160030 + #define IOCTL_PAR_IS_PORT_FREE 0x00160054 + +#endif /* NT_IOCTLS */ + +} DR_DRIVE_CONTROL_REQ; + +typedef struct _DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ { + DR_DEVICE_IOREQUEST DeviceIoRequest; + DWORD FsInformationClass; + DWORD Length; + BYTE Padding[24]; + union _QueryVolumeBuffer { + BYTE * bytes, byteArray, buf; + unsigned char * ucharArray, uchars; + char * str, charArray, chars; + struct _FILE_FS_VOLUME_INFORMATION * FsVolumeInformation; + struct _FILE_FS_SIZE_INFORMATION * FsSizeInformation; + struct _FILE_FS_FULL_SIZE_INFORMATION * FsFullSizeInformation; + struct _FILE_FS_DEVICE_INFORMATION * FsDeviceInformation; + struct _FILE_FS_ATTRIBUTE_INFORMATION * FsAttributeInformation; + } QueryVolumeBuffer; + void (*__destructor)(struct _DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ *); + int (*out)(struct _DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ *, struct stream *); + int (*in)(struct _DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ *, struct stream *); + + #define FileFsVolumeInformation 0x00000001 + #define FileFsSizeInformation 0x00000003 + #define FileFsAttributeInformation 0x00000005 + #define FileFsFullSizeInformation 0x00000007 + #define FileFsDeviceInformation 0x00000004 +} DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ; + +typedef struct _DR_DRIVE_SET_VOLUME_INFORMATION_REQ { + DR_DEVICE_IOREQUEST DeviceIoRequest; + DWORD FsInformationClass; + DWORD Length; + BYTE Padding[24]; + BYTE * SetVolumeBuffer; + void (*__destructor)(struct _DR_DRIVE_SET_VOLUME_INFORMATION_REQ *); + int (*out)(struct _DR_DRIVE_SET_VOLUME_INFORMATION_REQ *, struct stream *); + int (*in)(struct _DR_DRIVE_SET_VOLUME_INFORMATION_REQ *, struct stream *); +} DR_DRIVE_SET_VOLUME_INFORMATION_REQ; + +typedef struct _DR_DRIVE_SET_INFORMATION_REQ { + DR_DEVICE_IOREQUEST DeviceIoRequest; + DWORD FsInformationClass; + DWORD Length; + BYTE Padding[24]; + union _DrDriveSetInformationReq_Buffer { + BYTE bytes[124]; + FILE_BASIC_INFORMATION BasicInformation, basic; + QWORD EndOfFileInformation, eof; + BYTE DispositionInformation, disposition; + RDP_FILE_RENAME_INFORMATION RenameInformation, rename; + QWORD AllocationInformation, allocation; + } SetBuffer; + void (*__destructor)(struct _DR_DRIVE_SET_INFORMATION_REQ *); + int (*out)(struct _DR_DRIVE_SET_INFORMATION_REQ *, struct stream *); + int (*in)(struct _DR_DRIVE_SET_INFORMATION_REQ *, struct stream *); + + #define FileRenameInformation 0x0000000A + #define FileDispositionInformation 0x0000000D + #define FileAllocationInformation 0x00000013 + #define FileEndOfFileInformation 0x00000014 +} DR_DRIVE_SET_INFORMATION_REQ; + +typedef struct _DR_DRIVE_QUERY_DIRECTORY_REQ { + /* */ + /* The server issues a query directory request on a redirected */ + /* file system device. This request is used to obtain a directory */ + /* enumeration. */ + /* */ + DR_DEVICE_IOREQUEST DeviceIoRequest; + DWORD FsInformationClass; + BYTE InitialQuery; + DWORD PathLength; + BYTE Padding[23]; + BYTE Path[512]; + void (*__destructor)(struct _DR_DRIVE_QUERY_DIRECTORY_REQ *); + int (*out)(struct _DR_DRIVE_QUERY_DIRECTORY_REQ *, struct stream *); + int (*in)(struct _DR_DRIVE_QUERY_DIRECTORY_REQ *, struct stream *); + int (*setPath)(struct _DR_DRIVE_QUERY_DIRECTORY_REQ *, const char *); + + #define FileDirectoryInformation 0x00000001 + #define FileFullDirectoryInformation 0x00000002 + #define FileBothDirectoryInformation 0x00000003 + #define FileNamesInformation 0x0000000C +} DR_DRIVE_QUERY_DIRECTORY_REQ; + +typedef struct _DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ { + DR_DEVICE_IOREQUEST DeviceIoRequest; + BYTE WatchTree; + DWORD CompletionFilter; + BYTE * Padding[27]; + void (*__destructor)(struct _DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ *); + int (*out)(struct _DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ *, struct stream *); + int (*in)(struct _DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ *, struct stream *); + + #define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001 + #define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002 + #define FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004 + #define FILE_NOTIFY_CHANGE_SIZE 0x00000008 + #define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010 + #define FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020 + #define FILE_NOTIFY_CHANGE_CREATION 0x00000040 + #define FILE_NOTIFY_CHANGE_EA 0x00000080 + #define FILE_NOTIFY_CHANGE_SECURITY 0x00000100 + #define FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200 + #define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400 + #define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800 +} DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ; + +typedef struct _DR_DRIVE_LOCK_REQ { + DR_DEVICE_IOREQUEST DeviceIoRequest; + DWORD Operation; + DWORD F:1; +/* DWORD Padding1; */ + DWORD NumLocks; + BYTE Padding2[20]; + RDP_LOCK_INFO * Locks; + void (*__destructor)(struct _DR_DRIVE_LOCK_REQ *); + int (*out)(struct _DR_DRIVE_LOCK_REQ *, struct stream *); + int (*in)(struct _DR_DRIVE_LOCK_REQ *, struct stream *); + + #define RDP_LOWIO_OP_SHAREDLOCK 0x00000002 + #define RDP_LOWIO_OP_EXCLUSIVELOCK 0x00000003 + #define RDP_LOWIO_OP_UNLOCK 0x00000004 + #define RDP_LOWIO_OP_UNLOCK_MULTIPLE 0x00000005 +} DR_DRIVE_LOCK_REQ; + +typedef struct _DR_DRIVE_CORE_DEVICE_IOCOMPLETION { + DR_DEVICE_IOCOMPLETION DeviceIoResponse; + void (*__destructor)(struct _DR_DRIVE_CORE_DEVICE_IOCOMPLETION *); + int (*out)(struct _DR_DRIVE_CORE_DEVICE_IOCOMPLETION *, struct stream *); + int (*in)(struct _DR_DRIVE_CORE_DEVICE_IOCOMPLETION *, struct stream *); +} DR_DRIVE_CORE_DEVICE_IOCOMPLETION; + +typedef struct _DR_DRIVE_CREATE_RSP { + DR_CREATE_RSP DeviceCreateResponse; + void (*__destructor)(struct _DR_DRIVE_CREATE_RSP *); + int (*out)(struct _DR_DRIVE_CREATE_RSP *, struct stream *); + int (*in)(struct _DR_DRIVE_CREATE_RSP *, struct stream *); +} DR_DRIVE_CREATE_RSP; + +typedef struct _DR_DRIVE_CLOSE_RSP { + DR_CLOSE_RSP DeviceCloseResponse; + void (*__destructor)(struct _DR_DRIVE_CLOSE_RSP *); + int (*out)(struct _DR_DRIVE_CLOSE_RSP *, struct stream *); + int (*in)(struct _DR_DRIVE_CLOSE_RSP *, struct stream *); +} DR_DRIVE_CLOSE_RSP; + +typedef struct _DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP { + DR_DEVICE_IOCOMPLETION DeviceIoReply; + DWORD Length; + union _DrDriveQueryVolumeInformation_Buffer { + BYTE bytes[128]; + struct _FILE_FS_VOLUME_INFORMATION FsVolumeInformation, vol; + struct _FILE_FS_SIZE_INFORMATION FsSizeInformation, size; + struct _FILE_FS_FULL_SIZE_INFORMATION FsFullSizeInformation, fullsize; + struct _FILE_FS_DEVICE_INFORMATION FsDeviceInformation, device; + struct _FILE_FS_ATTRIBUTE_INFORMATION FsAttributeInformation, attrs; + } Buffer; + BYTE Padding; + void (*__destructor)(struct _DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP *); + int (*out)(struct _DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP *, struct stream *); + int (*in)(struct _DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP *, struct stream *); +} DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP; + +typedef struct _DR_DRIVE_SET_VOLUME_INFORMATION_RSP { + DR_DEVICE_IOCOMPLETION DeviceIoReply; + DWORD Length; + void (*__destructor)(struct _DR_DRIVE_SET_VOLUME_INFORMATION_RSP *); + int (*out)(struct _DR_DRIVE_SET_VOLUME_INFORMATION_RSP *, struct stream *); + int (*in)(struct _DR_DRIVE_SET_VOLUME_INFORMATION_RSP *, struct stream *); +} DR_DRIVE_SET_VOLUME_INFORMATION_RSP; + +typedef struct _DR_DRIVE_QUERY_INFORMATION_RSP { + DR_DEVICE_IOCOMPLETION DeviceIoReply; + DWORD Length; + union _DrDriveQueryInformationRsp_Buffer { + BYTE bytes[104], blob[104], data[104], raw[104], byteArray[104], binary[104]; + FILE_BASIC_INFORMATION basic, basicInformation, FileBasicInformation; + FILE_STANDARD_INFORMATION standard, standardInformation, FileStandardInformation; + FILE_ATTRIBUTE_TAG_INFORMATION attributeInformation, AttributeTagInformation; + FILE_ALL_INFORMATION all, fileAllInformation; + } Buffer; + void (*__destructor)(struct _DR_DRIVE_QUERY_INFORMATION_RSP *); + int (*out)(struct _DR_DRIVE_QUERY_INFORMATION_RSP *, struct stream *); + int (*in)(struct _DR_DRIVE_QUERY_INFORMATION_RSP *, struct stream *); +} DR_DRIVE_QUERY_INFORMATION_RSP; + +typedef struct _DR_DRIVE_QUERY_DIRECTORY_RSP { + DR_DEVICE_IOCOMPLETION DeviceIoReply; + DWORD Length; + union { + BYTE bytes[MAX_STREAM], data[MAX_STREAM]; + FILE_DIRECTORY_INFORMATION fileDirectoryInformation, directory; + FILE_BOTH_DIR_INFORMATION fileBothDirectoryInformation, both; + FILE_FULL_DIR_INFORMATION fileFullDirectoryInformation, full; + FILE_NAME_INFORMATION fileNameInformation, name; + FILE_NAMES_INFORMATION fileNamesInformation, names; + } Buffer; + BYTE Padding; + void (*__destructor)(struct _DR_DRIVE_QUERY_DIRECTORY_RSP *); + int (*out)(struct _DR_DRIVE_QUERY_DIRECTORY_RSP *, struct stream *); + int (*in)(struct _DR_DRIVE_QUERY_DIRECTORY_RSP *, struct stream *); +} DR_DRIVE_QUERY_DIRECTORY_RSP; + +typedef struct _DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP { + DR_DEVICE_IOCOMPLETION DeviceIoReply; + DWORD Length; + BYTE * Buffer; + BYTE Padding; + void (*__destructor)(struct _DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP *); + int (*out)(struct _DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP *, struct stream *); + int (*in)(struct _DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP *, struct stream *); +} DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP; + +typedef struct _DR_DRIVE_LOCK_RSP { + DR_DEVICE_IOCOMPLETION DeviceIoReply; + BYTE Padding[5]; + void (*__destructor)(struct _DR_DRIVE_LOCK_RSP *); + int (*out)(struct _DR_DRIVE_LOCK_RSP *, struct stream *); + int (*in)(struct _DR_DRIVE_LOCK_RSP *, struct stream *); +} DR_DRIVE_LOCK_RSP; + +typedef struct _DR_DRIVE_QUERY_INFORMATION_REQ { + DR_DEVICE_IOREQUEST DeviceIoRequest; + DWORD FsInformationClass; + DWORD Length; + BYTE Padding[24]; + union _QueryBuffer { + BYTE bytes[40], blob[40], data[40], raw[40], byteArray[40], binary[40]; + FILE_BASIC_INFORMATION basic, basicInformation, FileBasicInformation; + FILE_STANDARD_INFORMATION standard, standardInformation, FileStandardInformation; + FILE_ATTRIBUTE_TAG_INFORMATION attributeInformation, AttributeTagInformation; + } QueryBuffer; + void (*__destructor)(struct _DR_DRIVE_QUERY_INFORMATION_REQ *); + int (*out)(struct _DR_DRIVE_QUERY_INFORMATION_REQ *, struct stream *); + int (*in)(struct _DR_DRIVE_QUERY_INFORMATION_REQ *, struct stream *); + + #define FileBasicInformation 0x00000004 + #define FileStandardInformation 0x00000005 + #define FileAttributeTagInformation 0x00000035 +} DR_DRIVE_QUERY_INFORMATION_REQ; + +typedef struct _DR_DRIVE_SET_INFORMATION_RSP { + DR_DEVICE_IOCOMPLETION DeviceIoReply; + DWORD Length; + BYTE Padding; + void (*__destructor)(struct _DR_DRIVE_SET_INFORMATION_RSP *); + int (*out)(struct _DR_DRIVE_SET_INFORMATION_RSP *, struct stream *); + int (*in)(struct _DR_DRIVE_SET_INFORMATION_RSP *, struct stream *); +} DR_DRIVE_SET_INFORMATION_RSP; + +typedef union _STARTING_VCN_INPUT_BUFFER { + QWORD Value; +} STARTING_VCN_INPUT_BUFFER; + +typedef struct _EXTENTS { + QWORD NextVcn; + QWORD Lcn; +} EXTENTS; + +typedef struct _RETRIEVAL_POINTERS_BUFFER { + DWORD ExtentCount; + DWORD Unused; + QWORD StartingVcn; + EXTENTS * Extents; +} RETRIEVAL_POINTERS_BUFFER; + +typedef struct _FILE_OBJECTID_BUFFER { + BYTE ObjectId[16]; + union _FILE_OBJECTID_UNION { + BYTE bytes[48]; + struct _FILE_OBJECTID_MISC { + BYTE BirthVolumeId[16]; + BYTE BirthObjectId[16]; + BYTE DomainId[16]; + } Fields; + } ExtendedInfo; +} FILE_OBJECTID_BUFFER; + + +/*****************************************************************************/ + +typedef struct _MINSHALL_FRENCH_SYMLINK { + char XSym[5]; + char len[7]; + char md5sum[33]; + char target[1024]; + int (*in)(struct _MINSHALL_FRENCH_SYMLINK *, struct stream *); + int (*out)(struct _MINSHALL_FRENCH_SYMLINK *, struct stream *); + char * (*get)(struct _MINSHALL_FRENCH_SYMLINK *); + int (*set)(struct _MINSHALL_FRENCH_SYMLINK *, const char *); +} MINSHALL_FRENCH_SYMLINK; + +typedef struct _INTERIX_SYMLINK { + char magic[8]; + char * target; +} INTERIX_SYMLINK; + +typedef struct _INTERIX_DEV_FILE { + char magic[8]; + int64_t major; + int64_t minor; +} INTERIX_DEV_FILE; + + +/***/ + +typedef struct rdpdr_packet_header { + uint32_t magic; + uint32_t opcode; + uint32_t size; + uint32_t device_id; + uint32_t fhandle; + uint32_t uniqid; + uint32_t crc32; +} rdpdr_packet_header_t; + +typedef struct rdpdr_packet { + uint32_t magic; + uint32_t opcode; + uint32_t size; + uint32_t device_id; + uint32_t fhandle; + uint32_t uniqid; + uint32_t crc32; + uint8_t data[0]; +} rdpdr_packet_t; + + +typedef struct rdp_irq_data { + uint32_t device_id; + uint8_t type; + uint32_t mask; + uint8_t dtr; + uint8_t rts; + uint8_t cd; + uint8_t ri; + uint32_t mcr; + uint32_t msr; + uint32_t status; + uint32_t rx_len; + uint8_t rx_buf[0]; +} rdp_irq_data_t; + +typedef struct rdpfs_buf { + uint32_t len; + uint8_t buf[0]; +} rdpfs_buf_t, * rdpfs_buf_p; + + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/drdynvc_defs.h posixrdp/posixxrdp.orig/common/drdynvc_defs.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/drdynvc_defs.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/drdynvc_defs.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,267 @@ + +#ifndef __XRDP_DRDYNVC_DEFS_H__ +#define __XRDP_DRDYNVC_DEFS_H__ + +#include +#include "defines.h" +#include "ntstatus.h" +#include "arch.h" +#include "parse.h" +#include "trans.h" +#include "thread_calls.h" +#include "stream_list.h" + + +#if !defined(BYTE) +#define BYTE uint8_t +#endif +#if !defined(WORD) +#define WORD uint16_t +#endif +#if !defined(DWORD) +#define DWORD uint32_t +#endif +#if !defined(QWORD) +#define QWORD uint64_t +#endif + +#if !defined(MAX_CB) +#define MAX_CB 4 +#endif + +#if !defined(MAX_CHANNEL) +#define MAX_CHANNEL 12 +#endif + +#define DRDYNVC_NONE 0x00 +#define DRDYNVC_BYTE 0x00 +#define DRDYNVC_WORD 0x01 +#define DRDYNVC_DWORD 0x03 +#define DRDYNVC_DWORD_ALT 0x02 + +typedef struct _drdynvc_callback { + + #define RDPEDYC_MAGIC ((DWORD)0xccabba333) + DWORD magic; + DWORD callback_index; + + DWORD opid; /* the opid assigned by "get_opid()" */ + DWORD channel_id; + DWORD type; /* 0 = fd; 1 = trans */ + tbus fd; /* file descriptor over which to send reply */ + DWORD CompletionId; /* the CompletionId of the RDP request corresponding to the original operation */ + DWORD opcode; /* the rdpfs (or rdpport, rdpprinter, rdpsc) opcode of the original operation */ + DWORD uniqid; /* specified by the filesystem handler per transaction */ + DWORD flags; + BYTE cmd; + + DWORD seq; + DWORD idx; + DWORD val; + + tc_t mutex; + tc_t cv; + + struct trans * trans; /* trans channel (to be used instead of "fd" if type == 1) */ + struct _drdynvc * channel; /* pointer to the dynamic virtual channel to which the original operation pertains */ + + #define CBFLAG_NONE 0x00000000 /* no flags are set */ + #define CBFLAG_FINAL 0x00000001 /* the reply corresponds to the final (or only) step in a series */ + #define CBFLAG_INTERMEDIATE 0x00000002 /* the reply corresponds to an intermediate step in a series (rather than the final step) */ + #define CBFLAG_USERDATA 0x00000004 /* the userdata buffer contains data */ + #define CBFLAG_IOSTATUS 0x00000008 /* the IoStatus field is set */ + #define CBFLAG_FUNC 0x00000010 /* the "func" field points to a valid callback function that should be invoked */ + #define CBFLAG_IRQ 0x00000020 /* the current step is part of a pseudo-interrupt routine */ + #define CBFLAG_MUTEX 0x00000040 /* the mutex field should be handled appropriately */ + #define CBFLAG_SUPPRESS 0x00000080 /* do not transmit a reply message */ + #define CBFLAG_CMD 0x00000100 /* the cmd field indicates the IOCTL command */ + #define CBFLAG_MASK 0x00000200 /* the mask field contains a bitmask */ + + DWORD length; + BYTE * data; /* optional extra data */ +} callback_t; + +typedef struct _drdynvc { + DWORD index; + DWORD channel_id; + DWORD dynamic_channel_index; + DWORD pid; + BYTE version; + BYTE id_length; + WORD priority0; + WORD priority1; + WORD priority3; + WORD priority4; + BYTE name[48]; + BYTE initialized; + BYTE acknowledged; + callback_t callbacks[MAX_CB]; + DWORD top_opid; + tbus pending_opids[MAX_CB]; + tbus socket; + tc_t ilock; + tc_t icv; + stream_list_t * ihead; + DWORD ilen; + DWORD irem; + unsigned char istatus; + tc_t olock; + tc_t ocv; + DWORD olen; + DWORD orem; + stream_list_t * ohead; + unsigned char ostatus; + struct trans * ccon; +} drdynvc_t, rdpchan_t; + +typedef struct _drdynvc_list { + DWORD ChannelCount; + struct _drdynvc ** ChannelList; +} drdynvc_list_t, rdpchan_list_t; + + +#define RDPCHAN_OPEN 0x0001 +#define RDPCHAN_DATAFIRST 0x0002 +#define RDPCHAN_DATA 0x0003 +#define RDPCHAN_CLOSE 0x0004 +#define RDPCHAN_CAPABILITIES 0x0005 +#define RDPCHAN_QUERY 0x0006 +#define RDPCHAN_ERROR 0x0010 + +/*****************************************************************************/ + +#define DRDYNVC_MAX_PDU 0x0640 + /* = 1600 bytes */ + +#define DRDYNVC_CREATE 0x01 +#define DRDYNVC_DATAFIRST 0x02 +#define DRDYNVC_DATA 0x03 +#define DRDYNVC_CLOSE 0x04 +#define DRDYNVC_CAPABILITIES 0x05 + +#define DRDYNVC_VERSION1 0x0001 +#define DRDYNVC_VERSION2 0x0002 + +typedef struct _DYNVC_CAPS_VERSION1_RSP { + BYTE Cmd; + BYTE Sp; + BYTE cbChId; + BYTE Pad; + DWORD Version; + int (* out)(struct _DYNVC_CAPS_VERSION1_RSP *, struct stream *); + int (* in)(struct _DYNVC_CAPS_VERSION1_RSP *, struct stream *); + void (* destroy)(struct _DYNVC_CAPS_VERSION1_RSP *); +} DYNVC_CAPS_VERSION1, DYNVC_CAPS_RSP; + +typedef struct _DYNVC_CAPS_VERSION2 { + BYTE Cmd; + BYTE Sp; + BYTE cbChId; + BYTE Pad; + DWORD Version; + WORD PriorityCharge0; + WORD PriorityCharge1; + WORD PriorityCharge2; + WORD PriorityCharge3; + int (* out)(struct _DYNVC_CAPS_VERSION2 *, struct stream *); + int (* in)(struct _DYNVC_CAPS_VERSION2 *, struct stream *); + void (* destroy)(struct _DYNVC_CAPS_VERSION2 *); +} DYNVC_CAPS_VERSION2; + +typedef struct _DYNVC_CREATE_REQ { + BYTE Cmd; + BYTE Pri; + BYTE cbChId; + DWORD ChannelId; + int (* out)(struct _DYNVC_CREATE_REQ *, struct stream *); + int (* in)(struct _DYNVC_CREATE_REQ *, struct stream *); + void (* destroy)(struct _DYNVC_CREATE_REQ *); + BYTE ChannelName[48]; +} DYNVC_CREATE_REQ; + +typedef struct _DYNVC_CREATE_RSP { + BYTE Cmd; + BYTE Sp; + BYTE cbChId; + DWORD ChannelId; + DWORD CreationStatus; + int (* out)(struct _DYNVC_CREATE_RSP *, struct stream *); + int (* in)(struct _DYNVC_CREATE_RSP *, struct stream *); + void (* destroy)(struct _DYNVC_CREATE_RSP *); +} DYNVC_CREATE_RSP; + +typedef struct _DYNVC_DATA_FIRST { + BYTE Cmd; + BYTE Len; + BYTE cbChId; + DWORD ChannelId; + DWORD Length; /* total length of the message to be sent */ + int (* out)(struct _DYNVC_DATA_FIRST *, struct stream *); + int (* in)(struct _DYNVC_DATA_FIRST *, struct stream *); + void (* destroy)(struct _DYNVC_DATA_FIRST *); + BYTE Data[0]; /* the length of the data in this field is equal to 1,600 bytes minus the sum of the sizes of the previous fields */ +} DYNVC_DATA_FIRST; + +typedef struct _DYNVC_DATA { + BYTE Cmd; + BYTE Sp; + BYTE cbChId; + DWORD ChannelId; + DWORD Length; + int (* out)(struct _DYNVC_DATA *, struct stream *); + int (* in)(struct _DYNVC_DATA *, struct stream *); + void (* destroy)(struct _DYNVC_DATA *); + BYTE Data[0]; /* the length of the data in this field is equal to 1,600 bytes minus the sum of the sizes of the previous fields */ +} DYNVC_DATA; + +typedef struct _DYNVC_CLOSE { + BYTE Cmd; + BYTE Sp; + BYTE cbChId; + DWORD ChannelId; + int (* out)(struct _DYNVC_CLOSE *, struct stream *); + int (* in)(struct _DYNVC_CLOSE *, struct stream *); + void (* destroy)(struct _DYNVC_CLOSE *); +} DYNVC_CLOSE; + +typedef struct _DYNVC_HEADER { + BYTE Cmd; + BYTE Pri; + BYTE cbChId; +} DYNVC_HEADER; + +typedef union _DYNVC_UNION { + DYNVC_HEADER header; + DYNVC_CAPS_VERSION1 caps_version1; + DYNVC_CAPS_VERSION2 caps_version2; + DYNVC_CAPS_RSP caps_rdp; + DYNVC_CREATE_REQ create_req; + DYNVC_CREATE_RSP create_rsp; + DYNVC_DATA_FIRST datafirst; + DYNVC_DATA data; + DYNVC_CLOSE close; +} DYNVC_ANY; + +/***/ + +typedef struct rdpedyc_packet_header { + DWORD magic; + DWORD opcode; + DWORD size; + DWORD channel_id; + DWORD uniqid; + DWORD crc32; +} rdpedyc_packet_header_t; + +typedef struct rdpedyc_packet { + DWORD magic; + DWORD opcode; + DWORD size; + DWORD channel_id; + DWORD uniqid; + DWORD crc32; + BYTE data[0]; +} rdpedyc_packet_t; + + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/Makefile.am posixrdp/posixxrdp.orig/common/Makefile.am --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/Makefile.am 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/Makefile.am 2010-11-08 09:56:43.000000000 +0100 @@ -1,23 +1,52 @@ AM_CFLAGS = \ + -pthread \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ -DXRDP_SBIN_PATH=\"${sbindir}\" \ -DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \ - -DXRDP_PID_PATH=\"${localstatedir}/run\" + -DXRDP_PID_PATH=\"${localstatedir}/run\" \ + -D_FILE_OFFSET_BITS=64 \ + -D_REENTRANT \ + -D_GNU_SOURCE \ + -D_XOPEN_SOURCE_EXTENDED \ + -D_POSIX_PTHREAD_SEMATICS \ + -D_POSIX_PTHREADS + +LDFLAGS = \ + -lpthread lib_LTLIBRARIES = \ libcommon.la libcommon_la_SOURCES = \ + crc32.c \ + crc32.h \ d3des.c \ + dbg.c \ file.c \ list.c \ log.c \ os_calls.c \ + os_calls.h \ + rdpdr.h \ + rdpdr_methods.c \ + rdpdr_methods.h \ ssl_calls.c \ + stringlist.c \ thread_calls.c \ - trans.c + thread_calls.h \ + thread_macros.h \ + trans.c \ + trans.h \ + ringbuffer.c \ + ringbuffer.h \ + ntddser.h \ + ntstatus.h \ + nterrmsg.h \ + devredir_defs.h \ + drdynvc_defs.h \ + recording_defs.h \ + sound_defs.h libcommon_la_LIBADD = \ - -lcrypto \ - -lpthread + -lcrypto diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/ntddser.h posixrdp/posixxrdp.orig/common/ntddser.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/ntddser.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/ntddser.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,409 @@ +/* + * DDK definitions for serial port + * + * Copyright (C) 2006 Eric Pouech + * From w32api package + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef _NTDDSER_H_ +#define _NTDDSER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NT_IOCTLS +#define NT_IOCTLS + +#define IOCTL_SERIAL_CLEAR_STATS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 36, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_CLR_DTR \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 10, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_CLR_RTS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 13, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_CONFIG_SIZE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 32, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_BAUD_RATE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 20, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_CHARS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 22, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_COMMSTATUS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 27, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_DTRRTS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 30, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_HANDFLOW \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 24, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_LINE_CONTROL \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 21, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_MODEM_CONTROL \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 37, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_MODEMSTATUS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 26, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_PROPERTIES \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 29, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_STATS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 35, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_TIMEOUTS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 8, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_WAIT_MASK \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 16, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_IMMEDIATE_CHAR \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 6, METHOD_BUFFERED, FILE_ANY_ACCESS) +#ifndef IOCTL_SERIAL_LSRMST_INSERT +/* it's already defined in winioctl.h */ +#define IOCTL_SERIAL_LSRMST_INSERT \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 31, METHOD_BUFFERED, FILE_ANY_ACCESS) +#endif +#define IOCTL_SERIAL_PURGE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 19, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_RESET_DEVICE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 11, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_BAUD_RATE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 1, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_BREAK_ON \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 4, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_BREAK_OFF \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 5, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_CHARS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 23, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_DTR \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 9, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_FIFO_CONTROL \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 39, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_HANDFLOW \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 25, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_LINE_CONTROL \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 3, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_MODEM_CONTROL \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 38, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_QUEUE_SIZE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 2, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_RTS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 12, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_TIMEOUTS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 7, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_WAIT_MASK \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 17, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_XOFF \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 14, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_XON \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 15, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_WAIT_ON_MASK \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 18, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_XOFF_COUNTER \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 28, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#endif /* NT_IOCTLS */ + +typedef unsigned long ULONG; +typedef long LONG; +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef short SHORT; +typedef unsigned short WCHAR; +typedef UCHAR BOOLEAN; + +typedef struct _SERIAL_BAUD_RATE { + ULONG BaudRate; +} SERIAL_BAUD_RATE, *PSERIAL_BAUD_RATE; + +/* SERIAL_BAUD_RATE.BaudRate constants */ +#define SERIAL_BAUD_075 0x00000001 +#define SERIAL_BAUD_110 0x00000002 +#define SERIAL_BAUD_134_5 0x00000004 +#define SERIAL_BAUD_150 0x00000008 +#define SERIAL_BAUD_300 0x00000010 +#define SERIAL_BAUD_600 0x00000020 +#define SERIAL_BAUD_1200 0x00000040 +#define SERIAL_BAUD_1800 0x00000080 +#define SERIAL_BAUD_2400 0x00000100 +#define SERIAL_BAUD_4800 0x00000200 +#define SERIAL_BAUD_7200 0x00000400 +#define SERIAL_BAUD_9600 0x00000800 +#define SERIAL_BAUD_14400 0x00001000 +#define SERIAL_BAUD_19200 0x00002000 +#define SERIAL_BAUD_38400 0x00004000 +#define SERIAL_BAUD_56K 0x00008000 +#define SERIAL_BAUD_128K 0x00010000 +#define SERIAL_BAUD_115200 0x00020000 +#define SERIAL_BAUD_57600 0x00040000 +#define SERIAL_BAUD_USER 0x10000000 + +typedef struct _SERIAL_CHARS +{ + UCHAR EofChar; + UCHAR ErrorChar; + UCHAR BreakChar; + UCHAR EventChar; + UCHAR XonChar; + UCHAR XoffChar; +} SERIAL_CHARS, *PSERIAL_CHARS; + +typedef struct _SERIAL_STATUS +{ + ULONG Errors; + ULONG HoldReasons; + ULONG AmountInInQueue; + ULONG AmountInOutQueue; + UCHAR EofReceived; + UCHAR WaitForImmediate; +} SERIAL_STATUS, *PSERIAL_STATUS; + +typedef struct _SERIAL_HANDFLOW +{ + ULONG ControlHandShake; + ULONG FlowReplace; + LONG XonLimit; + LONG XoffLimit; +} SERIAL_HANDFLOW, *PSERIAL_HANDFLOW; + +#define SERIAL_DTR_MASK 0x00000003 +#define SERIAL_DTR_CONTROL 0x00000001 +#define SERIAL_DTR_HANDSHAKE 0x00000002 +#define SERIAL_CTS_HANDSHAKE 0x00000008 +#define SERIAL_DSR_HANDSHAKE 0x00000010 +#define SERIAL_DCD_HANDSHAKE 0x00000020 +#define SERIAL_OUT_HANDSHAKEMASK 0x00000038 +#define SERIAL_DSR_SENSITIVITY 0x00000040 +#define SERIAL_ERROR_ABORT 0x80000000 +#define SERIAL_CONTROL_INVALID 0x7fffff84 +#define SERIAL_AUTO_TRANSMIT 0x00000001 +#define SERIAL_AUTO_RECEIVE 0x00000002 +#define SERIAL_ERROR_CHAR 0x00000004 +#define SERIAL_NULL_STRIPPING 0x00000008 +#define SERIAL_BREAK_CHAR 0x00000010 +#define SERIAL_RTS_MASK 0x000000c0 +#define SERIAL_RTS_CONTROL 0x00000040 +#define SERIAL_RTS_HANDSHAKE 0x00000080 +#define SERIAL_TRANSMIT_TOGGLE 0x000000c0 +#define SERIAL_XOFF_CONTINUE 0x80000000 +#define SERIAL_FLOW_INVALID 0x7fffff20 + +typedef struct _SERIAL_LINE_CONTROL { + UCHAR StopBits; + UCHAR Parity; + UCHAR WordLength; +} SERIAL_LINE_CONTROL, *PSERIAL_LINE_CONTROL; + +/* SERIAL_LINE_CONTROL.StopBits constants */ +#define STOP_BIT_1 0x00 +#define STOP_BITS_1_5 0x01 +#define STOP_BITS_2 0x02 + +/* SERIAL_LINE_CONTROL.Parity constants */ +#define NO_PARITY 0x00 +#define ODD_PARITY 0x01 +#define EVEN_PARITY 0x02 +#define MARK_PARITY 0x03 +#define SPACE_PARITY 0x04 + +/* IOCTL_SERIAL_(GET_MODEM_CONTROL, SET_MODEM_CONTROL) flags */ +#define SERIAL_IOC_MCR_DTR 0x00000001 +#define SERIAL_IOC_MCR_RTS 0x00000002 +#define SERIAL_IOC_MCR_OUT1 0x00000004 +#define SERIAL_IOC_MCR_OUT2 0x00000008 +#define SERIAL_IOC_MCR_LOOP 0x00000010 + +typedef struct _SERIAL_COMMPROP +{ + USHORT PacketLength; + USHORT PacketVersion; + ULONG ServiceMask; + ULONG Reserved1; + ULONG MaxTxQueue; + ULONG MaxRxQueue; + ULONG MaxBaud; + ULONG ProvSubType; + ULONG ProvCapabilities; + ULONG SettableParams; + ULONG SettableBaud; + USHORT SettableData; + USHORT SettableStopParity; + ULONG CurrentTxQueue; + ULONG CurrentRxQueue; + ULONG ProvSpec1; + ULONG ProvSpec2; + WCHAR ProvChar[1]; +} SERIAL_COMMPROP, *PSERIAL_COMMPROP; + +/* SERIAL_COMMPROP.SettableParams flags */ +#define SERIAL_SP_PARITY 0x0001 +#define SERIAL_SP_BAUD 0x0002 +#define SERIAL_SP_DATABITS 0x0004 +#define SERIAL_SP_STOPBITS 0x0008 +#define SERIAL_SP_HANDSHAKING 0x0010 +#define SERIAL_SP_PARITY_CHECK 0x0020 +#define SERIAL_SP_CARRIER_DETECT 0x0040 + +/* SERIAL_COMMPROP.ProvCapabilities flags */ +#define SERIAL_PCF_DTRDSR 0x00000001 +#define SERIAL_PCF_RTSCTS 0x00000002 +#define SERIAL_PCF_CD 0x00000004 +#define SERIAL_PCF_PARITY_CHECK 0x00000008 +#define SERIAL_PCF_XONXOFF 0x00000010 +#define SERIAL_PCF_SETXCHAR 0x00000020 +#define SERIAL_PCF_TOTALTIMEOUTS 0x00000040 +#define SERIAL_PCF_INTTIMEOUTS 0x00000080 +#define SERIAL_PCF_SPECIALCHARS 0x00000100 +#define SERIAL_PCF_16BITMODE 0x00000200 + +/* SERIAL_COMMPROP.SettableData flags */ +#define SERIAL_DATABITS_5 0x0001 +#define SERIAL_DATABITS_6 0x0002 +#define SERIAL_DATABITS_7 0x0004 +#define SERIAL_DATABITS_8 0x0008 +#define SERIAL_DATABITS_16 0x0010 +#define SERIAL_DATABITS_16X 0x0020 + +/* SERIAL_COMMPROP.SettableStopParity flags */ +#define SERIAL_STOPBITS_10 0x0001 +#define SERIAL_STOPBITS_15 0x0002 +#define SERIAL_STOPBITS_20 0x0004 +#define SERIAL_PARITY_NONE 0x0100 +#define SERIAL_PARITY_ODD 0x0200 +#define SERIAL_PARITY_EVEN 0x0400 +#define SERIAL_PARITY_MARK 0x0800 +#define SERIAL_PARITY_SPACE 0x1000 + +typedef struct _SERIALPERF_STATS +{ + ULONG ReceivedCount; + ULONG TransmittedCount; + ULONG FrameErrorCount; + ULONG SerialOverrunErrorCount; + ULONG BufferOverrunErrorCount; + ULONG ParityErrorCount; +} SERIALPERF_STATS, *PSERIALPERF_STATS; + +typedef struct _SERIAL_TIMEOUTS +{ + ULONG ReadIntervalTimeout; + ULONG ReadTotalTimeoutMultiplier; + ULONG ReadTotalTimeoutConstant; + ULONG WriteTotalTimeoutMultiplier; + ULONG WriteTotalTimeoutConstant; +} SERIAL_TIMEOUTS, *PSERIAL_TIMEOUTS; + +/* IOCTL_SERIAL_(GET_WAIT_MASK, SET_WAIT_MASK, WAIT_ON_MASK) flags */ +#define SERIAL_EV_RXCHAR 0x0001 +#define SERIAL_EV_RXFLAG 0x0002 +#define SERIAL_EV_TXEMPTY 0x0004 +#define SERIAL_EV_CTS 0x0008 +#define SERIAL_EV_DSR 0x0010 +#define SERIAL_EV_RLSD 0x0020 +#define SERIAL_EV_BREAK 0x0040 +#define SERIAL_EV_ERR 0x0080 +#define SERIAL_EV_RING 0x0100 +#define SERIAL_EV_PERR 0x0200 +#define SERIAL_EV_RX80FULL 0x0400 +#define SERIAL_EV_EVENT1 0x0800 +#define SERIAL_EV_EVENT2 0x1000 + +/* IOCTL_SERIAL_LSRMST_INSERT constants */ +#define SERIAL_LSRMST_LSR_DATA 0x01 +#define SERIAL_LSRMST_LSR_NODATA 0x02 +#define SERIAL_LSRMST_MST 0x03 +#define SERIAL_LSRMST_ESCAPE 0x00 + +/* IOCTL_SERIAL_PURGE constants */ +#define SERIAL_PURGE_TXABORT 0x00000001 +#define SERIAL_PURGE_RXABORT 0x00000002 +#define SERIAL_PURGE_TXCLEAR 0x00000004 +#define SERIAL_PURGE_RXCLEAR 0x00000008 + +/* IOCTL_SERIAL_SET_FIFO_CONTROL constants */ +#define SERIAL_IOC_FCR_FIFO_ENABLE 0x00000001 +#define SERIAL_IOC_FCR_RCVR_RESET 0x00000002 +#define SERIAL_IOC_FCR_XMIT_RESET 0x00000004 +#define SERIAL_IOC_FCR_DMA_MODE 0x00000008 +#define SERIAL_IOC_FCR_RES1 0x00000010 +#define SERIAL_IOC_FCR_RES2 0x00000020 +#define SERIAL_IOC_FCR_RCVR_TRIGGER_LSB 0x00000040 +#define SERIAL_IOC_FCR_RCVR_TRIGGER_MSB 0x00000080 + +typedef struct _SERIAL_QUEUE_SIZE +{ + ULONG InSize; + ULONG OutSize; +} SERIAL_QUEUE_SIZE, *PSERIAL_QUEUE_SIZE; + +typedef struct _SERIAL_XOFF_COUNTER +{ + ULONG Timeout; + LONG Counter; + UCHAR XoffChar; +} SERIAL_XOFF_COUNTER, *PSERIAL_XOFF_COUNTER; + +typedef struct _SERIAL_BASIC_SETTINGS +{ + SERIAL_TIMEOUTS Timeouts; + SERIAL_HANDFLOW HandFlow; + ULONG RxFifo; + ULONG TxFifo; +} SERIAL_BASIC_SETTINGS, *PSERIAL_BASIC_SETTINGS; + +#define SERIAL_ERROR_BREAK 0x00000001 +#define SERIAL_ERROR_FRAMING 0x00000002 +#define SERIAL_ERROR_OVERRUN 0x00000004 +#define SERIAL_ERROR_QUEUEOVERRUN 0x00000008 +#define SERIAL_ERROR_PARITY 0x00000010 + +#define SERIAL_SP_UNSPECIFIED 0x00000000 +#define SERIAL_SP_RS232 0x00000001 +#define SERIAL_SP_PARALLEL 0x00000002 +#define SERIAL_SP_RS422 0x00000003 +#define SERIAL_SP_RS423 0x00000004 +#define SERIAL_SP_RS449 0x00000005 +#define SERIAL_SP_MODEM 0X00000006 +#define SERIAL_SP_FAX 0x00000021 +#define SERIAL_SP_SCANNER 0x00000022 +#define SERIAL_SP_BRIDGE 0x00000100 +#define SERIAL_SP_LAT 0x00000101 +#define SERIAL_SP_TELNET 0x00000102 +#define SERIAL_SP_X25 0x00000103 +#define SERIAL_SP_SERIALCOMM 0x00000001 + +#define SERIAL_TX_WAITING_FOR_CTS 0x00000001 +#define SERIAL_TX_WAITING_FOR_DSR 0x00000002 +#define SERIAL_TX_WAITING_FOR_DCD 0x00000004 +#define SERIAL_TX_WAITING_FOR_XON 0x00000008 +#define SERIAL_TX_WAITING_XOFF_SENT 0x00000010 +#define SERIAL_TX_WAITING_ON_BREAK 0x00000020 +#define SERIAL_RX_WAITING_FOR_DSR 0x00000040 + +#define SERIAL_DTR_STATE 0x00000001 +#define SERIAL_RTS_STATE 0x00000002 +#define SERIAL_CTS_STATE 0x00000010 +#define SERIAL_DSR_STATE 0x00000020 +#define SERIAL_RI_STATE 0x00000040 +#define SERIAL_DCD_STATE 0x00000080 + +typedef struct _SERIALCONFIG +{ + ULONG Size; + USHORT Version; + ULONG SubType; + ULONG ProvOffset; + ULONG ProviderSize; + WCHAR ProviderData[1]; +} SERIALCONFIG,*PSERIALCONFIG; + +#ifdef __cplusplus +} +#endif + +#endif /* _NTDDSER_H_ */ diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/nterrmsg.h posixrdp/posixxrdp.orig/common/nterrmsg.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/nterrmsg.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/nterrmsg.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,925 @@ +#if !defined(__XRDP_NT_ERR_MSG__) +#define __XRDP_NT_ERR_MSG__ + +#include + +typedef struct nterr_msg { + uint32_t ntstatus; + const char msg[48]; +} nterr_msg_t; + +#define NTERRMSG_ARRAY { \ + {0xC0000001, "UNSUCCESSFUL"}, \ + {0xC0000002, "NOT IMPLEMENTED"}, \ + {0xC0000003, "INVALID INFO CLASS"}, \ + {0xC0000004, "INFO LENGTH MISMATCH"}, \ + {0xC0000005, "ACCESS VIOLATION"}, \ + {0xC0000006, "IN PAGE ERROR"}, \ + {0xC0000007, "PAGEFILE QUOTA"}, \ + {0xC0000008, "INVALID HANDLE"}, \ + {0xC0000009, "BAD INITIAL STACK"}, \ + {0xC000000A, "BAD INITIAL PC"}, \ + {0xC000000B, "INVALID CID"}, \ + {0xC000000C, "TIMER NOT CANCELED"}, \ + {0xC000000D, "INVALID PARAMETER"}, \ + {0xC000000E, "NO SUCH DEVICE"}, \ + {0xC000000F, "NO SUCH FILE"}, \ + {0xC0000010, "INVALID DEVICE REQUEST"}, \ + {0xC0000011, "END OF FILE"}, \ + {0xC0000012, "WRONG VOLUME"}, \ + {0xC0000013, "NO MEDIA IN DEVICE"}, \ + {0xC0000014, "UNRECOGNIZED MEDIA"}, \ + {0xC0000015, "NONEXISTENT SECTOR"}, \ + {0xC0000016, "MORE PROCESSING REQUIRED"}, \ + {0xC0000017, "NO MEMORY"}, \ + {0xC0000018, "CONFLICTING ADDRESSES"}, \ + {0xC0000019, "NOT MAPPED VIEW"}, \ + {0xC000001A, "UNABLE TO FREE VM"}, \ + {0xC000001B, "UNABLE TO DELETE SECTION"}, \ + {0xC000001C, "INVALID SYSTEM SERVICE"}, \ + {0xC000001D, "ILLEGAL INSTRUCTION"}, \ + {0xC000001E, "INVALID LOCK SEQUENCE"}, \ + {0xC000001F, "INVALID VIEW SIZE"}, \ + {0xC0000020, "INVALID FILE FOR SECTION"}, \ + {0xC0000021, "ALREADY COMMITTED"}, \ + {0xC0000022, "ACCESS DENIED"}, \ + {0xC0000023, "BUFFER TOO SMALL"}, \ + {0xC0000024, "OBJECT TYPE MISMATCH"}, \ + {0xC0000025, "NONCONTINUABLE EXCEPTION"}, \ + {0xC0000026, "INVALID DISPOSITION"}, \ + {0xC0000027, "UNWIND"}, \ + {0xC0000028, "BAD STACK"}, \ + {0xC0000029, "INVALID UNWIND TARGET"}, \ + {0xC000002A, "NOT LOCKED"}, \ + {0xC000002B, "PARITY ERROR"}, \ + {0xC000002C, "UNABLE TO DECOMMIT VM"}, \ + {0xC000002D, "NOT COMMITTED"}, \ + {0xC000002E, "INVALID PORT ATTRIBUTES"}, \ + {0xC000002F, "PORT MESSAGE TOO LONG"}, \ + {0xC0000030, "INVALID PARAMETER MIX"}, \ + {0xC0000031, "INVALID QUOTA LOWER"}, \ + {0xC0000032, "DISK CORRUPT ERROR"}, \ + {0xC0000033, "OBJECT NAME INVALID"}, \ + {0xC0000034, "OBJECT NAME NOT FOUND"}, \ + {0xC0000035, "OBJECT NAME COLLISION"}, \ + {0xC0000037, "PORT DISCONNECTED"}, \ + {0xC0000038, "DEVICE ALREADY ATTACHED"}, \ + {0xC0000039, "OBJECT PATH INVALID"}, \ + {0xC000003A, "OBJECT PATH NOT FOUND"}, \ + {0xC000003B, "OBJECT PATH SYNTAX BAD"}, \ + {0xC000003C, "DATA OVERRUN"}, \ + {0xC000003D, "DATA LATE ERROR"}, \ + {0xC000003E, "DATA ERROR"}, \ + {0xC000003F, "CRC ERROR"}, \ + {0xC0000040, "SECTION TOO BIG"}, \ + {0xC0000041, "PORT CONNECTION REFUSED"}, \ + {0xC0000042, "INVALID PORT HANDLE"}, \ + {0xC0000043, "SHARING VIOLATION"}, \ + {0xC0000044, "QUOTA EXCEEDED"}, \ + {0xC0000045, "INVALID PAGE PROTECTION"}, \ + {0xC0000046, "MUTANT NOT OWNED"}, \ + {0xC0000047, "SEMAPHORE LIMIT EXCEEDED"}, \ + {0xC0000048, "PORT ALREADY SET"}, \ + {0xC0000049, "SECTION NOT IMAGE"}, \ + {0xC000004A, "SUSPEND COUNT EXCEEDED"}, \ + {0xC000004B, "THREAD IS TERMINATING"}, \ + {0xC000004C, "BAD WORKING SET LIMIT"}, \ + {0xC000004D, "INCOMPATIBLE FILE MAP"}, \ + {0xC000004E, "SECTION PROTECTION"}, \ + {0xC000004F, "EAS NOT SUPPORTED"}, \ + {0xC0000050, "EA TOO LARGE"}, \ + {0xC0000051, "NONEXISTENT EA ENTRY"}, \ + {0xC0000052, "NO EAS ON FILE"}, \ + {0xC0000053, "EA CORRUPT ERROR"}, \ + {0xC0000054, "FILE LOCK CONFLICT"}, \ + {0xC0000055, "LOCK NOT GRANTED"}, \ + {0xC0000056, "DELETE PENDING"}, \ + {0xC0000057, "CTL FILE NOT SUPPORTED"}, \ + {0xC0000058, "UNKNOWN REVISION"}, \ + {0xC0000059, "REVISION MISMATCH"}, \ + {0xC000005A, "INVALID OWNER"}, \ + {0xC000005B, "INVALID PRIMARY GROUP"}, \ + {0xC000005C, "NO IMPERSONATION TOKEN"}, \ + {0xC000005D, "CANT DISABLE MANDATORY"}, \ + {0xC000005E, "NO LOGON SERVERS"}, \ + {0xC000005F, "NO SUCH LOGON SESSION"}, \ + {0xC0000060, "NO SUCH PRIVILEGE"}, \ + {0xC0000061, "PRIVILEGE NOT HELD"}, \ + {0xC0000062, "INVALID ACCOUNT NAME"}, \ + {0xC0000063, "USER EXISTS"}, \ + {0xC0000064, "NO SUCH USER"}, \ + {0xC0000065, "GROUP EXISTS"}, \ + {0xC0000066, "NO SUCH GROUP"}, \ + {0xC0000067, "MEMBER IN GROUP"}, \ + {0xC0000068, "MEMBER NOT IN GROUP"}, \ + {0xC0000069, "LAST ADMIN"}, \ + {0xC000006A, "WRONG PASSWORD"}, \ + {0xC000006B, "ILL FORMED PASSWORD"}, \ + {0xC000006C, "PASSWORD RESTRICTION"}, \ + {0xC000006D, "LOGON FAILURE"}, \ + {0xC000006E, "ACCOUNT RESTRICTION"}, \ + {0xC000006F, "INVALID LOGON HOURS"}, \ + {0xC0000070, "INVALID WORKSTATION"}, \ + {0xC0000071, "PASSWORD EXPIRED"}, \ + {0xC0000072, "ACCOUNT DISABLED"}, \ + {0xC0000073, "NONE MAPPED"}, \ + {0xC0000074, "TOO MANY LUIDS REQUESTED"}, \ + {0xC0000075, "LUIDS EXHAUSTED"}, \ + {0xC0000076, "INVALID SUB AUTHORITY"}, \ + {0xC0000077, "INVALID ACL"}, \ + {0xC0000078, "INVALID SID"}, \ + {0xC0000079, "INVALID SECURITY DESCR"}, \ + {0xC000007A, "PROCEDURE NOT FOUND"}, \ + {0xC000007B, "INVALID IMAGE FORMAT"}, \ + {0xC000007C, "NO TOKEN"}, \ + {0xC000007D, "BAD INHERITANCE ACL"}, \ + {0xC000007E, "RANGE NOT LOCKED"}, \ + {0xC000007F, "DISK FULL"}, \ + {0xC0000080, "SERVER DISABLED"}, \ + {0xC0000081, "SERVER NOT DISABLED"}, \ + {0xC0000082, "TOO MANY GUIDS REQUESTED"}, \ + {0xC0000083, "GUIDS EXHAUSTED"}, \ + {0xC0000084, "INVALID ID AUTHORITY"}, \ + {0xC0000085, "AGENTS EXHAUSTED"}, \ + {0xC0000086, "INVALID VOLUME LABEL"}, \ + {0xC0000087, "SECTION NOT EXTENDED"}, \ + {0xC0000088, "NOT MAPPED DATA"}, \ + {0xC0000089, "RESOURCE DATA NOT FOUND"}, \ + {0xC000008A, "RESOURCE TYPE NOT FOUND"}, \ + {0xC000008B, "RESOURCE NAME NOT FOUND"}, \ + {0xC000008C, "ARRAY BOUNDS EXCEEDED"}, \ + {0xC000008D, "FLOAT DENORMAL OPERAND"}, \ + {0xC000008E, "FLOAT DIVIDE BY ZERO"}, \ + {0xC000008F, "FLOAT INEXACT RESULT"}, \ + {0xC0000090, "FLOAT INVALID OPERATION"}, \ + {0xC0000091, "FLOAT OVERFLOW"}, \ + {0xC0000092, "FLOAT STACK CHECK"}, \ + {0xC0000093, "FLOAT UNDERFLOW"}, \ + {0xC0000094, "INTEGER DIVIDE BY ZERO"}, \ + {0xC0000095, "INTEGER OVERFLOW"}, \ + {0xC0000096, "PRIVILEGED INSTRUCTION"}, \ + {0xC0000097, "TOO MANY PAGING FILES"}, \ + {0xC0000098, "FILE INVALID"}, \ + {0xC0000099, "ALLOTTED SPACE EXCEEDED"}, \ + {0xC000009A, "INSUFFICIENT RESOURCES"}, \ + {0xC000009B, "DFS EXIT PATH FOUND"}, \ + {0xC000009C, "DEVICE DATA ERROR"}, \ + {0xC000009D, "DEVICE NOT CONNECTED"}, \ + {0xC000009E, "DEVICE POWER FAILURE"}, \ + {0xC000009F, "FREE VM NOT AT BASE"}, \ + {0xC00000A0, "MEMORY NOT ALLOCATED"}, \ + {0xC00000A1, "WORKING SET QUOTA"}, \ + {0xC00000A2, "MEDIA WRITE PROTECTED"}, \ + {0xC00000A3, "DEVICE NOT READY"}, \ + {0xC00000A4, "INVALID GROUP ATTRIBUTES"}, \ + {0xC00000A5, "BAD IMPERSONATION LEVEL"}, \ + {0xC00000A6, "CANT OPEN ANONYMOUS"}, \ + {0xC00000A7, "BAD VALIDATION CLASS"}, \ + {0xC00000A8, "BAD TOKEN TYPE"}, \ + {0xC00000A9, "BAD MASTER BOOT RECORD"}, \ + {0xC00000AA, "INSTRUCTION MISALIGNMENT"}, \ + {0xC00000AB, "INSTANCE NOT AVAILABLE"}, \ + {0xC00000AC, "PIPE NOT AVAILABLE"}, \ + {0xC00000AD, "INVALID PIPE STATE"}, \ + {0xC00000AE, "PIPE BUSY"}, \ + {0xC00000AF, "ILLEGAL FUNCTION"}, \ + {0xC00000B0, "PIPE DISCONNECTED"}, \ + {0xC00000B1, "PIPE CLOSING"}, \ + {0xC00000B2, "PIPE CONNECTED"}, \ + {0xC00000B3, "PIPE LISTENING"}, \ + {0xC00000B4, "INVALID READ MODE"}, \ + {0xC00000B5, "IO TIMEOUT"}, \ + {0xC00000B6, "FILE FORCED CLOSED"}, \ + {0xC00000B7, "PROFILING NOT STARTED"}, \ + {0xC00000B8, "PROFILING NOT STOPPED"}, \ + {0xC00000B9, "COULD NOT INTERPRET"}, \ + {0xC00000BA, "FILE IS A DIRECTORY"}, \ + {0xC00000BB, "NOT SUPPORTED"}, \ + {0xC00000BC, "REMOTE NOT LISTENING"}, \ + {0xC00000BD, "DUPLICATE NAME"}, \ + {0xC00000BE, "BAD NETWORK PATH"}, \ + {0xC00000BF, "NETWORK BUSY"}, \ + {0xC00000C0, "DEVICE DOES NOT EXIST"}, \ + {0xC00000C1, "TOO MANY COMMANDS"}, \ + {0xC00000C2, "ADAPTER HARDWARE ERROR"}, \ + {0xC00000C3, "INVALID NETWORK RESPONSE"}, \ + {0xC00000C4, "UNEXPECTED NETWORK ERROR"}, \ + {0xC00000C5, "BAD REMOTE ADAPTER"}, \ + {0xC00000C6, "PRINT QUEUE FULL"}, \ + {0xC00000C7, "NO SPOOL SPACE"}, \ + {0xC00000C8, "PRINT CANCELLED"}, \ + {0xC00000C9, "NETWORK NAME DELETED"}, \ + {0xC00000CA, "NETWORK ACCESS DENIED"}, \ + {0xC00000CB, "BAD DEVICE TYPE"}, \ + {0xC00000CC, "BAD NETWORK NAME"}, \ + {0xC00000CD, "TOO MANY NAMES"}, \ + {0xC00000CE, "TOO MANY SESSIONS"}, \ + {0xC00000CF, "SHARING PAUSED"}, \ + {0xC00000D0, "REQUEST NOT ACCEPTED"}, \ + {0xC00000D1, "REDIRECTOR PAUSED"}, \ + {0xC00000D2, "NET WRITE FAULT"}, \ + {0xC00000D3, "PROFILING AT LIMIT"}, \ + {0xC00000D4, "NOT SAME DEVICE"}, \ + {0xC00000D5, "FILE RENAMED"}, \ + {0xC00000D6, "VIRTUAL CIRCUIT CLOSED"}, \ + {0xC00000D7, "NO SECURITY ON OBJECT"}, \ + {0xC00000D8, "CANT WAIT"}, \ + {0xC00000D9, "PIPE EMPTY"}, \ + {0xC00000DA, "CANT ACCESS DOMAIN INFO"}, \ + {0xC00000DB, "CANT TERMINATE SELF"}, \ + {0xC00000DC, "INVALID SERVER STATE"}, \ + {0xC00000DD, "INVALID DOMAIN STATE"}, \ + {0xC00000DE, "INVALID DOMAIN ROLE"}, \ + {0xC00000DF, "NO SUCH DOMAIN"}, \ + {0xC00000E0, "DOMAIN EXISTS"}, \ + {0xC00000E1, "DOMAIN LIMIT EXCEEDED"}, \ + {0xC00000E2, "OPLOCK NOT GRANTED"}, \ + {0xC00000E3, "INVALID OPLOCK PROTOCOL"}, \ + {0xC00000E4, "INTERNAL DB CORRUPTION"}, \ + {0xC00000E5, "INTERNAL ERROR"}, \ + {0xC00000E6, "GENERIC NOT MAPPED"}, \ + {0xC00000E7, "BAD DESCRIPTOR FORMAT"}, \ + {0xC00000E8, "INVALID USER BUFFER"}, \ + {0xC00000E9, "UNEXPECTED IO ERROR"}, \ + {0xC00000EA, "UNEXPECTED MM CREATE ERR"}, \ + {0xC00000EB, "UNEXPECTED MM MAP ERROR"}, \ + {0xC00000EC, "UNEXPECTED MM EXTEND ERR"}, \ + {0xC00000ED, "NOT LOGON PROCESS"}, \ + {0xC00000EE, "LOGON SESSION EXISTS"}, \ + {0xC00000EF, "INVALID PARAMETER 1"}, \ + {0xC00000F0, "INVALID PARAMETER 2"}, \ + {0xC00000F1, "INVALID PARAMETER 3"}, \ + {0xC00000F2, "INVALID PARAMETER 4"}, \ + {0xC00000F3, "INVALID PARAMETER 5"}, \ + {0xC00000F4, "INVALID PARAMETER 6"}, \ + {0xC00000F5, "INVALID PARAMETER 7"}, \ + {0xC00000F6, "INVALID PARAMETER 8"}, \ + {0xC00000F7, "INVALID PARAMETER 9"}, \ + {0xC00000F8, "INVALID PARAMETER 10"}, \ + {0xC00000F9, "INVALID PARAMETER 11"}, \ + {0xC00000FA, "INVALID PARAMETER 12"}, \ + {0xC00000FB, "REDIRECTOR NOT STARTED"}, \ + {0xC00000FC, "REDIRECTOR STARTED"}, \ + {0xC00000FD, "STACK OVERFLOW"}, \ + {0xC00000FE, "NO SUCH PACKAGE"}, \ + {0xC00000FF, "BAD FUNCTION TABLE"}, \ + {0xC0000100, "VARIABLE NOT FOUND"}, \ + {0xC0000101, "DIRECTORY NOT EMPTY"}, \ + {0xC0000102, "FILE CORRUPT ERROR"}, \ + {0xC0000103, "NOT A DIRECTORY"}, \ + {0xC0000104, "BAD LOGON SESSION STATE"}, \ + {0xC0000105, "LOGON SESSION COLLISION"}, \ + {0xC0000106, "NAME TOO LONG"}, \ + {0xC0000107, "FILES OPEN"}, \ + {0xC0000108, "CONNECTION IN USE"}, \ + {0xC0000109, "MESSAGE NOT FOUND"}, \ + {0xC000010A, "PROCESS IS TERMINATING"}, \ + {0xC000010B, "INVALID LOGON TYPE"}, \ + {0xC000010C, "NO GUID TRANSLATION"}, \ + {0xC000010D, "CANNOT IMPERSONATE"}, \ + {0xC000010E, "IMAGE ALREADY LOADED"}, \ + {0xC000010F, "ABIOS NOT PRESENT"}, \ + {0xC0000110, "ABIOS LID NOT EXIST"}, \ + {0xC0000111, "ABIOS LID ALREADY OWNED"}, \ + {0xC0000112, "ABIOS NOT LID OWNER"}, \ + {0xC0000113, "ABIOS INVALID COMMAND"}, \ + {0xC0000114, "ABIOS INVALID LID"}, \ + {0xC0000115, "ABIOS SELECTOR NOT AVAILABLE"}, \ + {0xC0000116, "ABIOS INVALID SELECTOR"}, \ + {0xC0000117, "NO LDT"}, \ + {0xC0000118, "INVALID LDT SIZE"}, \ + {0xC0000119, "INVALID LDT OFFSET"}, \ + {0xC000011A, "INVALID LDT DESCRIPTOR"}, \ + {0xC000011B, "INVALID IMAGE NE FORMAT"}, \ + {0xC000011C, "RXACT INVALID STATE"}, \ + {0xC000011D, "RXACT COMMIT FAILURE"}, \ + {0xC000011E, "MAPPED FILE SIZE ZERO"}, \ + {0xC000011F, "TOO MANY OPENED FILES"}, \ + {0xC0000120, "CANCELLED"}, \ + {0xC0000121, "CANNOT DELETE"}, \ + {0xC0000122, "INVALID COMPUTER NAME"}, \ + {0xC0000123, "FILE DELETED"}, \ + {0xC0000124, "SPECIAL ACCOUNT"}, \ + {0xC0000125, "SPECIAL GROUP"}, \ + {0xC0000126, "SPECIAL USER"}, \ + {0xC0000127, "MEMBERS PRIMARY GROUP"}, \ + {0xC0000128, "FILE CLOSED"}, \ + {0xC0000129, "TOO MANY THREADS"}, \ + {0xC000012A, "THREAD NOT IN PROCESS"}, \ + {0xC000012B, "TOKEN ALREADY IN USE"}, \ + {0xC000012C, "PAGEFILE QUOTA EXCEEDED"}, \ + {0xC000012D, "COMMITMENT LIMIT"}, \ + {0xC000012E, "INVALID IMAGE LE FORMAT"}, \ + {0xC000012F, "INVALID IMAGE NOT MZ"}, \ + {0xC0000130, "INVALID IMAGE PROTECT"}, \ + {0xC0000131, "INVALID IMAGE WIN 16"}, \ + {0xC0000132, "LOGON SERVER CONFLICT"}, \ + {0xC0000133, "TIME DIFFERENCE AT DC"}, \ + {0xC0000134, "SYNCHRONIZATION REQUIRED"}, \ + {0xC0000135, "DLL NOT FOUND"}, \ + {0xC0000136, "OPEN FAILED"}, \ + {0xC0000137, "IO PRIVILEGE FAILED"}, \ + {0xC0000138, "ORDINAL NOT FOUND"}, \ + {0xC0000139, "ENTRYPOINT NOT FOUND"}, \ + {0xC000013A, "CONTROL C EXIT"}, \ + {0xC000013B, "LOCAL DISCONNECT"}, \ + {0xC000013C, "REMOTE DISCONNECT"}, \ + {0xC000013D, "REMOTE RESOURCES"}, \ + {0xC000013E, "LINK FAILED"}, \ + {0xC000013F, "LINK TIMEOUT"}, \ + {0xC0000140, "INVALID CONNECTION"}, \ + {0xC0000141, "INVALID ADDRESS"}, \ + {0xC0000142, "DLL INIT FAILED"}, \ + {0xC0000143, "MISSING SYSTEMFILE"}, \ + {0xC0000144, "UNHANDLED EXCEPTION"}, \ + {0xC0000145, "APP INIT FAILURE"}, \ + {0xC0000146, "PAGEFILE CREATE FAILED"}, \ + {0xC0000147, "NO PAGEFILE"}, \ + {0xC0000148, "INVALID LEVEL"}, \ + {0xC0000149, "WRONG PASSWORD CORE"}, \ + {0xC000014A, "ILLEGAL FLOAT CONTEXT"}, \ + {0xC000014B, "PIPE BROKEN"}, \ + {0xC000014C, "REGISTRY CORRUPT"}, \ + {0xC000014D, "REGISTRY IO FAILED"}, \ + {0xC000014E, "NO EVENT PAIR"}, \ + {0xC000014F, "UNRECOGNIZED VOLUME"}, \ + {0xC0000150, "SERIAL NO DEVICE INITED"}, \ + {0xC0000151, "NO SUCH ALIAS"}, \ + {0xC0000152, "MEMBER NOT IN ALIAS"}, \ + {0xC0000153, "MEMBER IN ALIAS"}, \ + {0xC0000154, "ALIAS EXISTS"}, \ + {0xC0000155, "LOGON NOT GRANTED"}, \ + {0xC0000156, "TOO MANY SECRETS"}, \ + {0xC0000157, "SECRET TOO LONG"}, \ + {0xC0000158, "INTERNAL DB ERROR"}, \ + {0xC0000159, "FULLSCREEN MODE"}, \ + {0xC000015A, "TOO MANY CONTEXT IDS"}, \ + {0xC000015B, "LOGON TYPE NOT GRANTED"}, \ + {0xC000015C, "NOT REGISTRY FILE"}, \ + {0xC000015D, "NT CROSS ENCRYPTION REQUIRED"}, \ + {0xC000015E, "DOMAIN CTRLR CONFIG ERROR"}, \ + {0xC000015F, "FT MISSING MEMBER"}, \ + {0xC0000160, "ILL FORMED SERVICE ENTRY"}, \ + {0xC0000161, "ILLEGAL CHARACTER"}, \ + {0xC0000162, "UNMAPPABLE CHARACTER"}, \ + {0xC0000163, "UNDEFINED CHARACTER"}, \ + {0xC0000164, "FLOPPY VOLUME"}, \ + {0xC0000165, "FLOPPY ID MARK NOT FOUND"}, \ + {0xC0000166, "FLOPPY WRONG CYLINDER"}, \ + {0xC0000167, "FLOPPY UNKNOWN ERROR"}, \ + {0xC0000168, "FLOPPY BAD REGISTERS"}, \ + {0xC0000169, "DISK RECALIBRATE FAILED"}, \ + {0xC000016A, "DISK OPERATION FAILED"}, \ + {0xC000016B, "DISK RESET FAILED"}, \ + {0xC000016C, "SHARED IRQ BUSY"}, \ + {0xC000016D, "FT ORPHANING"}, \ + {0xC000016E, "BIOS FAILED TO CONNECT INTERRUPT"}, \ + {0xC0000172, "PARTITION FAILURE"}, \ + {0xC0000173, "INVALID BLOCK LENGTH"}, \ + {0xC0000174, "DEVICE NOT PARTITIONED"}, \ + {0xC0000175, "UNABLE TO LOCK MEDIA"}, \ + {0xC0000176, "UNABLE TO UNLOAD MEDIA"}, \ + {0xC0000177, "EOM OVERFLOW"}, \ + {0xC0000178, "NO MEDIA"}, \ + {0xC000017A, "NO SUCH MEMBER"}, \ + {0xC000017B, "INVALID MEMBER"}, \ + {0xC000017C, "KEY DELETED"}, \ + {0xC000017D, "NO LOG SPACE"}, \ + {0xC000017E, "TOO MANY SIDS"}, \ + {0xC000017F, "LM CROSS ENCRYPTION REQUIRED"}, \ + {0xC0000180, "KEY HAS CHILDREN"}, \ + {0xC0000181, "CHILD MUST BE VOLATILE"}, \ + {0xC0000182, "DEVICE CONFIGURATION ERROR"}, \ + {0xC0000183, "DRIVER INTERNAL ERROR"}, \ + {0xC0000184, "INVALID DEVICE STATE"}, \ + {0xC0000185, "IO DEVICE ERROR"}, \ + {0xC0000186, "DEVICE PROTOCOL ERROR"}, \ + {0xC0000187, "BACKUP CONTROLLER"}, \ + {0xC0000188, "LOG FILE FULL"}, \ + {0xC0000189, "TOO LATE"}, \ + {0xC000018A, "NO TRUST LSA SECRET"}, \ + {0xC000018B, "NO TRUST SAM ACCOUNT"}, \ + {0xC000018C, "TRUSTED DOMAIN FAILURE"}, \ + {0xC000018D, "TRUSTED RELATIONSHIP FAILURE"}, \ + {0xC000018E, "EVENTLOG FILE CORRUPT"}, \ + {0xC000018F, "EVENTLOG CANT START"}, \ + {0xC0000190, "TRUST FAILURE"}, \ + {0xC0000191, "MUTANT LIMIT EXCEEDED"}, \ + {0xC0000192, "NETLOGON NOT STARTED"}, \ + {0xC0000193, "ACCOUNT EXPIRED"}, \ + {0xC0000194, "POSSIBLE DEADLOCK"}, \ + {0xC0000195, "NETWORK CREDENTIAL CONFLICT"}, \ + {0xC0000196, "REMOTE SESSION LIMIT"}, \ + {0xC0000197, "EVENTLOG FILE CHANGED"}, \ + {0xC0000198, "NOLOGON INTERDOMAIN TRUST ACCOUNT"}, \ + {0xC0000199, "NOLOGON WORKSTATION TRUST ACCOUNT"}, \ + {0xC000019A, "NOLOGON SERVER TRUST ACCOUNT"}, \ + {0xC000019B, "DOMAIN TRUST INCONSISTENT"}, \ + {0xC000019C, "FS DRIVER REQUIRED"}, \ + {0xC0000202, "NO USER SESSION KEY"}, \ + {0xC0000203, "USER SESSION DELETED"}, \ + {0xC0000204, "RESOURCE LANG NOT FOUND"}, \ + {0xC0000205, "INSUFF SERVER RESOURCES"}, \ + {0xC0000206, "INVALID BUFFER SIZE"}, \ + {0xC0000207, "INVALID ADDRESS COMPONENT"}, \ + {0xC0000208, "INVALID ADDRESS WILDCARD"}, \ + {0xC0000209, "TOO MANY ADDRESSES"}, \ + {0xC000020A, "ADDRESS ALREADY EXISTS"}, \ + {0xC000020B, "ADDRESS CLOSED"}, \ + {0xC000020C, "CONNECTION DISCONNECTED"}, \ + {0xC000020D, "CONNECTION RESET"}, \ + {0xC000020E, "TOO MANY NODES"}, \ + {0xC000020F, "TRANSACTION ABORTED"}, \ + {0xC0000210, "TRANSACTION TIMED OUT"}, \ + {0xC0000211, "TRANSACTION NO RELEASE"}, \ + {0xC0000212, "TRANSACTION NO MATCH"}, \ + {0xC0000213, "TRANSACTION RESPONDED"}, \ + {0xC0000214, "TRANSACTION INVALID ID"}, \ + {0xC0000215, "TRANSACTION INVALID TYPE"}, \ + {0xC0000216, "NOT SERVER SESSION"}, \ + {0xC0000217, "NOT CLIENT SESSION"}, \ + {0xC0000218, "CANNOT LOAD REGISTRY FILE"}, \ + {0xC0000219, "DEBUG ATTACH FAILED"}, \ + {0xC000021A, "SYSTEM PROCESS TERMINATED"}, \ + {0xC000021B, "DATA NOT ACCEPTED"}, \ + {0xC000021C, "NO BROWSER SERVERS FOUND"}, \ + {0xC000021D, "VDM HARD ERROR"}, \ + {0xC000021E, "DRIVER CANCEL TIMEOUT"}, \ + {0xC000021F, "REPLY MESSAGE MISMATCH"}, \ + {0xC0000220, "MAPPED ALIGNMENT"}, \ + {0xC0000221, "IMAGE CHECKSUM MISMATCH"}, \ + {0xC0000222, "LOST WRITEBEHIND DATA"}, \ + {0xC0000223, "CLIENT SERVER PARAMETERS INVALID"}, \ + {0xC0000224, "PASSWORD MUST CHANGE"}, \ + {0xC0000225, "NOT FOUND"}, \ + {0xC0000226, "NOT TINY STREAM"}, \ + {0xC0000227, "RECOVERY FAILURE"}, \ + {0xC0000228, "STACK OVERFLOW READ"}, \ + {0xC0000229, "FAIL CHECK"}, \ + {0xC000022A, "DUPLICATE OBJECTID"}, \ + {0xC000022B, "OBJECTID EXISTS"}, \ + {0xC000022C, "CONVERT TO LARGE"}, \ + {0xC000022D, "RETRY"}, \ + {0xC000022E, "FOUND OUT OF SCOPE"}, \ + {0xC000022F, "ALLOCATE BUCKET"}, \ + {0xC0000230, "PROPSET NOT FOUND"}, \ + {0xC0000231, "MARSHALL OVERFLOW"}, \ + {0xC0000232, "INVALID VARIANT"}, \ + {0xC0000233, "DOMAIN CONTROLLER NOT FOUND"}, \ + {0xC0000234, "ACCOUNT LOCKED OUT"}, \ + {0xC0000235, "HANDLE NOT CLOSABLE"}, \ + {0xC0000236, "CONNECTION REFUSED"}, \ + {0xC0000237, "GRACEFUL DISCONNECT"}, \ + {0xC0000238, "ADDRESS ALREADY ASSOCIATED"}, \ + {0xC0000239, "ADDRESS NOT ASSOCIATED"}, \ + {0xC000023A, "CONNECTION INVALID"}, \ + {0xC000023B, "CONNECTION ACTIVE"}, \ + {0xC000023C, "NETWORK UNREACHABLE"}, \ + {0xC000023D, "HOST UNREACHABLE"}, \ + {0xC000023E, "PROTOCOL UNREACHABLE"}, \ + {0xC000023F, "PORT UNREACHABLE"}, \ + {0xC0000240, "REQUEST ABORTED"}, \ + {0xC0000241, "CONNECTION ABORTED"}, \ + {0xC0000242, "BAD COMPRESSION BUFFER"}, \ + {0xC0000243, "USER MAPPED FILE"}, \ + {0xC0000244, "AUDIT FAILED"}, \ + {0xC0000245, "TIMER RESOLUTION NOT SET"}, \ + {0xC0000246, "CONNECTION COUNT LIMIT"}, \ + {0xC0000247, "LOGIN TIME RESTRICTION"}, \ + {0xC0000248, "LOGIN WKSTA RESTRICTION"}, \ + {0xC0000249, "IMAGE MP UP MISMATCH"}, \ + {0xC0000250, "INSUFFICIENT LOGON INFO"}, \ + {0xC0000251, "BAD DLL ENTRYPOINT"}, \ + {0xC0000252, "BAD SERVICE ENTRYPOINT"}, \ + {0xC0000253, "LPC REPLY LOST"}, \ + {0xC0000254, "IP ADDRESS CONFLICT1"}, \ + {0xC0000255, "IP ADDRESS CONFLICT2"}, \ + {0xC0000256, "REGISTRY QUOTA LIMIT"}, \ + {0xC0000257, "PATH NOT COVERED"}, \ + {0xC0000258, "NO CALLBACK ACTIVE"}, \ + {0xC0000259, "LICENSE QUOTA EXCEEDED"}, \ + {0xC000025A, "PWD TOO SHORT"}, \ + {0xC000025B, "PWD TOO RECENT"}, \ + {0xC000025C, "PWD HISTORY CONFLICT"}, \ + {0xC000025E, "PLUGPLAY NO DEVICE"}, \ + {0xC000025F, "UNSUPPORTED COMPRESSION"}, \ + {0xC0000260, "INVALID HW PROFILE"}, \ + {0xC0000261, "INVALID PLUGPLAY DEVICE PATH"}, \ + {0xC0000262, "DRIVER ORDINAL NOT FOUND"}, \ + {0xC0000263, "DRIVER ENTRYPOINT NOT FOUND"}, \ + {0xC0000264, "RESOURCE NOT OWNED"}, \ + {0xC0000265, "TOO MANY LINKS"}, \ + {0xC0000266, "QUOTA LIST INCONSISTENT"}, \ + {0xC0000267, "FILE IS OFFLINE"}, \ + {0xC0000268, "EVALUATION EXPIRATION"}, \ + {0xC0000269, "ILLEGAL DLL RELOCATION"}, \ + {0xC000026A, "LICENSE VIOLATION"}, \ + {0xC000026B, "DLL INIT FAILED LOGOFF"}, \ + {0xC000026C, "DRIVER UNABLE TO LOAD"}, \ + {0xC000026D, "DFS UNAVAILABLE"}, \ + {0xC000026E, "VOLUME DISMOUNTED"}, \ + {0xC000026F, "WX86 INTERNAL ERROR"}, \ + {0xC0000270, "WX86 FLOAT STACK CHECK"}, \ + {0xC0000271, "VALIDATE CONTINUE"}, \ + {0xC0000272, "NO MATCH"}, \ + {0xC0000273, "NO MORE MATCHES"}, \ + {0xC0000275, "NOT A REPARSE POINT"}, \ + {0xC0000276, "IO REPARSE TAG INVALID"}, \ + {0xC0000277, "IO REPARSE TAG MISMATCH"}, \ + {0xC0000278, "IO REPARSE DATA INVALID"}, \ + {0xC0000279, "IO REPARSE TAG NOT HANDLED"}, \ + {0xC0000280, "REPARSE POINT NOT RESOLVED"}, \ + {0xC0000281, "DIRECTORY IS A REPARSE POINT"}, \ + {0xC0000282, "RANGE LIST CONFLICT"}, \ + {0xC0000283, "SOURCE ELEMENT EMPTY"}, \ + {0xC0000284, "DESTINATION ELEMENT FULL"}, \ + {0xC0000285, "ILLEGAL ELEMENT ADDRESS"}, \ + {0xC0000286, "MAGAZINE NOT PRESENT"}, \ + {0xC0000287, "REINITIALIZATION NEEDED"}, \ + {0xC000028A, "ENCRYPTION FAILED"}, \ + {0xC000028B, "DECRYPTION FAILED"}, \ + {0xC000028C, "RANGE NOT FOUND"}, \ + {0xC000028D, "NO RECOVERY POLICY"}, \ + {0xC000028E, "NO EFS"}, \ + {0xC000028F, "WRONG EFS"}, \ + {0xC0000290, "NO USER KEYS"}, \ + {0xC0000291, "FILE NOT ENCRYPTED"}, \ + {0xC0000292, "NOT EXPORT FORMAT"}, \ + {0xC0000293, "FILE ENCRYPTED"}, \ + {0xC0000295, "WMI GUID NOT FOUND"}, \ + {0xC0000296, "WMI INSTANCE NOT FOUND"}, \ + {0xC0000297, "WMI ITEMID NOT FOUND"}, \ + {0xC0000298, "WMI TRY AGAIN"}, \ + {0xC0000299, "SHARED POLICY"}, \ + {0xC000029A, "POLICY OBJECT NOT FOUND"}, \ + {0xC000029B, "POLICY ONLY IN DS"}, \ + {0xC000029C, "VOLUME NOT UPGRADED"}, \ + {0xC000029D, "REMOTE STORAGE NOT ACTIVE"}, \ + {0xC000029E, "REMOTE STORAGE MEDIA ERROR"}, \ + {0xC000029F, "NO TRACKING SERVICE"}, \ + {0xC00002A0, "SERVER SID MISMATCH"}, \ + {0xC00002A1, "DS NO ATTRIBUTE OR VALUE"}, \ + {0xC00002A2, "DS INVALID ATTRIBUTE SYNTAX"}, \ + {0xC00002A3, "DS ATTRIBUTE TYPE UNDEFINED"}, \ + {0xC00002A4, "DS ATTRIBUTE OR VALUE EXISTS"}, \ + {0xC00002A5, "DS BUSY"}, \ + {0xC00002A6, "DS UNAVAILABLE"}, \ + {0xC00002A7, "DS NO RIDS ALLOCATED"}, \ + {0xC00002A8, "DS NO MORE RIDS"}, \ + {0xC00002A9, "DS INCORRECT ROLE OWNER"}, \ + {0xC00002AA, "DS RIDMGR INIT ERROR"}, \ + {0xC00002AB, "DS OBJ CLASS VIOLATION"}, \ + {0xC00002AC, "DS CANT ON NON LEAF"}, \ + {0xC00002AD, "DS CANT ON RDN"}, \ + {0xC00002AE, "DS CANT MOD OBJ CLASS"}, \ + {0xC00002AF, "DS CROSS DOM MOVE FAILED"}, \ + {0xC00002B0, "DS GC NOT AVAILABLE"}, \ + {0xC00002B1, "DIRECTORY SERVICE REQUIRED"}, \ + {0xC00002B2, "REPARSE ATTRIBUTE CONFLICT"}, \ + {0xC00002B3, "CANT ENABLE DENY ONLY"}, \ + {0xC00002B4, "FLOAT MULTIPLE FAULTS"}, \ + {0xC00002B5, "FLOAT MULTIPLE TRAPS"}, \ + {0xC00002B6, "DEVICE REMOVED"}, \ + {0xC00002B7, "JOURNAL DELETE IN PROGRESS"}, \ + {0xC00002B8, "JOURNAL NOT ACTIVE"}, \ + {0xC00002B9, "NOINTERFACE"}, \ + {0xC00002C1, "DS ADMIN LIMIT EXCEEDED"}, \ + {0xC00002C2, "DRIVER FAILED SLEEP"}, \ + {0xC00002C3, "MUTUAL AUTHENTICATION FAILED"}, \ + {0xC00002C4, "CORRUPT SYSTEM FILE"}, \ + {0xC00002C5, "DATATYPE MISALIGNMENT ERROR"}, \ + {0xC00002C6, "WMI READ ONLY"}, \ + {0xC00002C7, "WMI SET FAILURE"}, \ + {0xC00002C8, "COMMITMENT MINIMUM"}, \ + {0xC00002C9, "REG NAT CONSUMPTION"}, \ + {0xC00002CA, "TRANSPORT FULL"}, \ + {0xC00002CB, "DS SAM INIT FAILURE"}, \ + {0xC00002CC, "ONLY IF CONNECTED"}, \ + {0xC00002CD, "DS SENSITIVE GROUP VIOLATION"}, \ + {0xC00002CE, "PNP RESTART ENUMERATION"}, \ + {0xC00002CF, "JOURNAL ENTRY DELETED"}, \ + {0xC00002D0, "DS CANT MOD PRIMARYGROUPID"}, \ + {0xC00002D1, "SYSTEM IMAGE BAD SIGNATURE"}, \ + {0xC00002D2, "PNP REBOOT REQUIRED"}, \ + {0xC00002D3, "POWER STATE INVALID"}, \ + {0xC00002D4, "DS INVALID GROUP TYPE"}, \ + {0xC00002D5, "DS NO NEST GLOBALGROUP IN MIXEDDOMAIN"}, \ + {0xC00002D6, "DS NO NEST LOCALGROUP IN MIXEDDOMAIN"}, \ + {0xC00002D7, "DS GLOBAL CANT HAVE LOCAL MEMBER"}, \ + {0xC00002D8, "DS GLOBAL CANT HAVE UNIVERSAL MEMBER"}, \ + {0xC00002D9, "DS UNIVERSAL CANT HAVE LOCAL MEMBER"}, \ + {0xC00002DA, "DS GLOBAL CANT HAVE CROSSDOMAIN MEMBER"}, \ + {0xC00002DB, "DS LOCAL CANT HAVE CROSSDOMAIN LOCAL MEMBER"}, \ + {0xC00002DC, "DS HAVE PRIMARY MEMBERS"}, \ + {0xC00002DD, "WMI NOT SUPPORTED"}, \ + {0xC00002DE, "INSUFFICIENT POWER"}, \ + {0xC00002DF, "SAM NEED BOOTKEY PASSWORD"}, \ + {0xC00002E0, "SAM NEED BOOTKEY FLOPPY"}, \ + {0xC00002E1, "DS CANT START"}, \ + {0xC00002E2, "DS INIT FAILURE"}, \ + {0xC00002E3, "SAM INIT FAILURE"}, \ + {0xC00002E4, "DS GC REQUIRED"}, \ + {0xC00002E5, "DS LOCAL MEMBER OF LOCAL ONLY"}, \ + {0xC00002E6, "DS NO FPO IN UNIVERSAL GROUPS"}, \ + {0xC00002E7, "DS MACHINE ACCOUNT QUOTA EXCEEDED"}, \ + {0xC00002E8, "MULTIPLE FAULT VIOLATION"}, \ + {0xC00002E9, "CURRENT DOMAIN NOT ALLOWED"}, \ + {0xC00002EA, "CANNOT MAKE"}, \ + {0xC00002EB, "SYSTEM SHUTDOWN"}, \ + {0xC00002EC, "DS INIT FAILURE CONSOLE"}, \ + {0xC00002ED, "DS SAM INIT FAILURE CONSOLE"}, \ + {0xC00002EE, "UNFINISHED CONTEXT DELETED"}, \ + {0xC00002EF, "NO TGT REPLY"}, \ + {0xC00002F0, "OBJECTID NOT FOUND"}, \ + {0xC00002F1, "NO IP ADDRESSES"}, \ + {0xC00002F2, "WRONG CREDENTIAL HANDLE"}, \ + {0xC00002F3, "CRYPTO SYSTEM INVALID"}, \ + {0xC00002F4, "MAX REFERRALS EXCEEDED"}, \ + {0xC00002F5, "MUST BE KDC"}, \ + {0xC00002F6, "STRONG CRYPTO NOT SUPPORTED"}, \ + {0xC00002F7, "TOO MANY PRINCIPALS"}, \ + {0xC00002F8, "NO PA DATA"}, \ + {0xC00002F9, "PKINIT NAME MISMATCH"}, \ + {0xC00002FA, "SMARTCARD LOGON REQUIRED"}, \ + {0xC00002FB, "KDC INVALID REQUEST"}, \ + {0xC00002FC, "KDC UNABLE TO REFER"}, \ + {0xC00002FD, "KDC UNKNOWN ETYPE"}, \ + {0xC00002FE, "SHUTDOWN IN PROGRESS"}, \ + {0xC00002FF, "SERVER SHUTDOWN IN PROGRESS"}, \ + {0xC0000300, "NOT SUPPORTED ON SBS"}, \ + {0xC0000301, "WMI GUID DISCONNECTED"}, \ + {0xC0000302, "WMI ALREADY DISABLED"}, \ + {0xC0000303, "WMI ALREADY ENABLED"}, \ + {0xC0000304, "MFT TOO FRAGMENTED"}, \ + {0xC0000305, "COPY PROTECTION FAILURE"}, \ + {0xC0000306, "CSS AUTHENTICATION FAILURE"}, \ + {0xC0000307, "CSS KEY NOT PRESENT"}, \ + {0xC0000308, "CSS KEY NOT ESTABLISHED"}, \ + {0xC0000309, "CSS SCRAMBLED SECTOR"}, \ + {0xC000030A, "CSS REGION MISMATCH"}, \ + {0xC000030B, "CSS RESETS EXHAUSTED"}, \ + {0xC0000320, "PKINIT FAILURE"}, \ + {0xC0000321, "SMARTCARD SUBSYSTEM FAILURE"}, \ + {0xC0000322, "NO KERB KEY"}, \ + {0xC0000350, "HOST DOWN"}, \ + {0xC0000351, "UNSUPPORTED PREAUTH"}, \ + {0xC0000352, "EFS ALG BLOB TOO BIG"}, \ + {0xC0000353, "PORT NOT SET"}, \ + {0xC0000354, "DEBUGGER INACTIVE"}, \ + {0xC0000355, "DS VERSION CHECK FAILURE"}, \ + {0xC0000356, "AUDITING DISABLED"}, \ + {0xC0000357, "PRENT4 MACHINE ACCOUNT"}, \ + {0xC0000358, "DS AG CANT HAVE UNIVERSAL MEMBER"}, \ + {0xC0000359, "INVALID IMAGE WIN 32"}, \ + {0xC000035A, "INVALID IMAGE WIN 64"}, \ + {0xC000035B, "BAD BINDINGS"}, \ + {0xC000035C, "NETWORK SESSION EXPIRED"}, \ + {0xC000035D, "APPHELP BLOCK"}, \ + {0xC000035E, "ALL SIDS FILTERED"}, \ + {0xC000035F, "NOT SAFE MODE DRIVER"}, \ + {0xC0000361, "ACCESS DISABLED BY POLICY DEFAULT"}, \ + {0xC0000362, "ACCESS DISABLED BY POLICY PATH"}, \ + {0xC0000363, "ACCESS DISABLED BY POLICY PUBLISHER"}, \ + {0xC0000364, "ACCESS DISABLED BY POLICY OTHER"}, \ + {0xC0000365, "FAILED DRIVER ENTRY"}, \ + {0xC0000366, "DEVICE ENUMERATION ERROR"}, \ + {0xC0000367, "WAIT FOR OPLOCK"}, \ + {0xC0000368, "MOUNT POINT NOT RESOLVED"}, \ + {0xC0000369, "INVALID DEVICE OBJECT PARAMETER"}, \ + {0xC000036A, "MCA OCCURED"}, \ + {0xC000036B, "DRIVER BLOCKED CRITICAL"}, \ + {0xC000036C, "DRIVER BLOCKED"}, \ + {0xC000036D, "DRIVER DATABASE ERROR"}, \ + {0xC000036E, "SYSTEM HIVE TOO LARGE"}, \ + {0xC000036F, "INVALID IMPORT OF NON DLL"}, \ + {0xC0000380, "SMARTCARD WRONG PIN"}, \ + {0xC0000381, "SMARTCARD CARD BLOCKED"}, \ + {0xC0000382, "SMARTCARD CARD NOT AUTHENTICATED"}, \ + {0xC0000383, "SMARTCARD NO CARD"}, \ + {0xC0000384, "SMARTCARD NO KEY CONTAINER"}, \ + {0xC0000385, "SMARTCARD NO CERTIFICATE"}, \ + {0xC0000386, "SMARTCARD NO KEYSET"}, \ + {0xC0000387, "SMARTCARD IO ERROR"}, \ + {0xC0000388, "DOWNGRADE DETECTED"}, \ + {0xC0000389, "SMARTCARD CERT REVOKED"}, \ + {0xC000038A, "ISSUING CA UNTRUSTED"}, \ + {0xC000038B, "REVOCATION OFFLINE C"}, \ + {0xC000038C, "PKINIT CLIENT FAILURE"}, \ + {0xC000038D, "SMARTCARD CERT EXPIRED"}, \ + {0xC000038E, "DRIVER FAILED PRIOR UNLOAD"}, \ + {0xC000038F, "SMARTCARD SILENT CONTEXT"}, \ + {0xC0000401, "PER USER TRUST QUOTA EXCEEDED"}, \ + {0xC0000402, "ALL USER TRUST QUOTA EXCEEDED"}, \ + {0xC0000403, "USER DELETE TRUST QUOTA EXCEEDED"}, \ + {0xC0000404, "DS NAME NOT UNIQUE"}, \ + {0xC0000405, "DS DUPLICATE ID FOUND"}, \ + {0xC0000406, "DS GROUP CONVERSION ERROR"}, \ + {0xC0000407, "VOLSNAP PREPARE HIBERNATE"}, \ + {0xC0000408, "USER2USER REQUIRED"}, \ + {0xC0000409, "STACK BUFFER OVERRUN"}, \ + {0xC000040A, "NO S4U PROT SUPPORT"}, \ + {0xC000040B, "CROSSREALM DELEGATION FAILURE"}, \ + {0xC000040C, "REVOCATION OFFLINE KDC"}, \ + {0xC000040D, "ISSUING CA UNTRUSTED KDC"}, \ + {0xC000040E, "KDC CERT EXPIRED"}, \ + {0xC000040F, "KDC CERT REVOKED"}, \ + {0xC0000410, "PARAMETER QUOTA EXCEEDED"}, \ + {0xC0000411, "HIBERNATION FAILURE"}, \ + {0xC0000412, "DELAY LOAD FAILED"}, \ + {0xC0000413, "AUTHENTICATION FIREWALL FAILED"}, \ + {0xC0000414, "VDM DISALLOWED"}, \ + {0xC0000415, "HUNG DISPLAY DRIVER THREAD"}, \ + {0xC0009898, "WOW ASSERTION"}, \ + {0xC0020001, "RPC NT INVALID STRING BINDING"}, \ + {0xC0020002, "RPC NT WRONG KIND OF BINDING"}, \ + {0xC0020003, "RPC NT INVALID BINDING"}, \ + {0xC0020004, "RPC NT PROTSEQ NOT SUPPORTED"}, \ + {0xC0020005, "RPC NT INVALID RPC PROTSEQ"}, \ + {0xC0020006, "RPC NT INVALID STRING UUID"}, \ + {0xC0020007, "RPC NT INVALID ENDPOINT FORMAT"}, \ + {0xC0020008, "RPC NT INVALID NET ADDR"}, \ + {0xC0020009, "RPC NT NO ENDPOINT FOUND"}, \ + {0xC002000A, "RPC NT INVALID TIMEOUT"}, \ + {0xC002000B, "RPC NT OBJECT NOT FOUND"}, \ + {0xC002000C, "RPC NT ALREADY REGISTERED"}, \ + {0xC002000D, "RPC NT TYPE ALREADY REGISTERED"}, \ + {0xC002000E, "RPC NT ALREADY LISTENING"}, \ + {0xC002000F, "RPC NT NO PROTSEQS REGISTERED"}, \ + {0xC0020010, "RPC NT NOT LISTENING"}, \ + {0xC0020011, "RPC NT UNKNOWN MGR TYPE"}, \ + {0xC0020012, "RPC NT UNKNOWN IF"}, \ + {0xC0020013, "RPC NT NO BINDINGS"}, \ + {0xC0020014, "RPC NT NO PROTSEQS"}, \ + {0xC0020015, "RPC NT CANT CREATE ENDPOINT"}, \ + {0xC0020016, "RPC NT OUT OF RESOURCES"}, \ + {0xC0020017, "RPC NT SERVER UNAVAILABLE"}, \ + {0xC0020018, "RPC NT SERVER TOO BUSY"}, \ + {0xC0020019, "RPC NT INVALID NETWORK OPTIONS"}, \ + {0xC002001A, "RPC NT NO CALL ACTIVE"}, \ + {0xC002001B, "RPC NT CALL FAILED"}, \ + {0xC002001C, "RPC NT CALL FAILED DNE"}, \ + {0xC002001D, "RPC NT PROTOCOL ERROR"}, \ + {0xC002001F, "RPC NT UNSUPPORTED TRANS SYN"}, \ + {0xC0020021, "RPC NT UNSUPPORTED TYPE"}, \ + {0xC0020022, "RPC NT INVALID TAG"}, \ + {0xC0020023, "RPC NT INVALID BOUND"}, \ + {0xC0020024, "RPC NT NO ENTRY NAME"}, \ + {0xC0020025, "RPC NT INVALID NAME SYNTAX"}, \ + {0xC0020026, "RPC NT UNSUPPORTED NAME SYNTAX"}, \ + {0xC0020028, "RPC NT UUID NO ADDRESS"}, \ + {0xC0020029, "RPC NT DUPLICATE ENDPOINT"}, \ + {0xC002002A, "RPC NT UNKNOWN AUTHN TYPE"}, \ + {0xC002002B, "RPC NT MAX CALLS TOO SMALL"}, \ + {0xC002002C, "RPC NT STRING TOO LONG"}, \ + {0xC002002D, "RPC NT PROTSEQ NOT FOUND"}, \ + {0xC002002E, "RPC NT PROCNUM OUT OF RANGE"}, \ + {0xC002002F, "RPC NT BINDING HAS NO AUTH"}, \ + {0xC0020030, "RPC NT UNKNOWN AUTHN SERVICE"}, \ + {0xC0020031, "RPC NT UNKNOWN AUTHN LEVEL"}, \ + {0xC0020032, "RPC NT INVALID AUTH IDENTITY"}, \ + {0xC0020033, "RPC NT UNKNOWN AUTHZ SERVICE"}, \ + {0xC0020034, "EPT NT INVALID ENTRY"}, \ + {0xC0020035, "EPT NT CANT PERFORM OP"}, \ + {0xC0020036, "EPT NT NOT REGISTERED"}, \ + {0xC0020037, "RPC NT NOTHING TO EXPORT"}, \ + {0xC0020038, "RPC NT INCOMPLETE NAME"}, \ + {0xC0020039, "RPC NT INVALID VERS OPTION"}, \ + {0xC002003A, "RPC NT NO MORE MEMBERS"}, \ + {0xC002003B, "RPC NT NOT ALL OBJS UNEXPORTED"}, \ + {0xC002003C, "RPC NT INTERFACE NOT FOUND"}, \ + {0xC002003D, "RPC NT ENTRY ALREADY EXISTS"}, \ + {0xC002003E, "RPC NT ENTRY NOT FOUND"}, \ + {0xC002003F, "RPC NT NAME SERVICE UNAVAILABLE"}, \ + {0xC0020040, "RPC NT INVALID NAF ID"}, \ + {0xC0020041, "RPC NT CANNOT SUPPORT"}, \ + {0xC0020042, "RPC NT NO CONTEXT AVAILABLE"}, \ + {0xC0020043, "RPC NT INTERNAL ERROR"}, \ + {0xC0020044, "RPC NT ZERO DIVIDE"}, \ + {0xC0020045, "RPC NT ADDRESS ERROR"}, \ + {0xC0020046, "RPC NT FP DIV ZERO"}, \ + {0xC0020047, "RPC NT FP UNDERFLOW"}, \ + {0xC0020048, "RPC NT FP OVERFLOW"}, \ + {0xC0020049, "RPC NT CALL IN PROGRESS"}, \ + {0xC002004A, "RPC NT NO MORE BINDINGS"}, \ + {0xC002004B, "RPC NT GROUP MEMBER NOT FOUND"}, \ + {0xC002004C, "EPT NT CANT CREATE"}, \ + {0xC002004D, "RPC NT INVALID OBJECT"}, \ + {0xC002004F, "RPC NT NO INTERFACES"}, \ + {0xC0020050, "RPC NT CALL CANCELLED"}, \ + {0xC0020051, "RPC NT BINDING INCOMPLETE"}, \ + {0xC0020052, "RPC NT COMM FAILURE"}, \ + {0xC0020053, "RPC NT UNSUPPORTED AUTHN LEVEL"}, \ + {0xC0020054, "RPC NT NO PRINC NAME"}, \ + {0xC0020055, "RPC NT NOT RPC ERROR"}, \ + {0xC0020057, "RPC NT SEC PKG ERROR"}, \ + {0xC0020058, "RPC NT NOT CANCELLED"}, \ + {0xC0020062, "RPC NT INVALID ASYNC HANDLE"}, \ + {0xC0020063, "RPC NT INVALID ASYNC CALL"}, \ + {0xC0030001, "RPC NT NO MORE ENTRIES"}, \ + {0xC0030002, "RPC NT SS CHAR TRANS OPEN FAIL"}, \ + {0xC0030003, "RPC NT SS CHAR TRANS SHORT FILE"}, \ + {0xC0030004, "RPC NT SS IN NULL CONTEXT"}, \ + {0xC0030005, "RPC NT SS CONTEXT MISMATCH"}, \ + {0xC0030006, "RPC NT SS CONTEXT DAMAGED"}, \ + {0xC0030007, "RPC NT SS HANDLES MISMATCH"}, \ + {0xC0030008, "RPC NT SS CANNOT GET CALL HANDLE"}, \ + {0xC0030009, "RPC NT NULL REF POINTER"}, \ + {0xC003000A, "RPC NT ENUM VALUE OUT OF RANGE"}, \ + {0xC003000B, "RPC NT BYTE COUNT TOO SMALL"}, \ + {0xC003000C, "RPC NT BAD STUB DATA"}, \ + {0xC0030059, "RPC NT INVALID ES ACTION"}, \ + {0xC003005A, "RPC NT WRONG ES VERSION"}, \ + {0xC003005B, "RPC NT WRONG STUB VERSION"}, \ + {0xC003005C, "RPC NT INVALID PIPE OBJECT"}, \ + {0xC003005D, "RPC NT INVALID PIPE OPERATION"}, \ + {0xC003005E, "RPC NT WRONG PIPE VERSION"}, \ + {0xC003005F, "RPC NT PIPE CLOSED"}, \ + {0xC0030060, "RPC NT PIPE DISCIPLINE ERROR"}, \ + {0xC0030061, "RPC NT PIPE EMPTY"}, \ + {0xC0040035, "PNP BAD MPS TABLE"}, \ + {0xC0040036, "PNP TRANSLATION FAILED"}, \ + {0xC0040037, "PNP IRQ TRANSLATION FAILED"}, \ + {0xC0040038, "PNP INVALID ID"}, \ + {0xC00A0001, "CTX WINSTATION NAME INVALID"}, \ + {0xC00A0002, "CTX INVALID PD"}, \ + {0xC00A0003, "CTX PD NOT FOUND"}, \ + {0xC00A0006, "CTX CLOSE PENDING"}, \ + {0xC00A0007, "CTX NO OUTBUF"}, \ + {0xC00A0008, "CTX MODEM INF NOT FOUND"}, \ + {0xC00A0009, "CTX INVALID MODEMNAME"}, \ + {0xC00A000A, "CTX RESPONSE ERROR"}, \ + {0xC00A000B, "CTX MODEM RESPONSE TIMEOUT"}, \ + {0xC00A000C, "CTX MODEM RESPONSE NO CARRIER"}, \ + {0xC00A000D, "CTX MODEM RESPONSE NO DIALTONE"}, \ + {0xC00A000E, "CTX MODEM RESPONSE BUSY"}, \ + {0xC00A000F, "CTX MODEM RESPONSE VOICE"}, \ + {0xC00A0010, "CTX TD ERROR"}, \ + {0xC00A0012, "CTX LICENSE CLIENT INVALID"}, \ + {0xC00A0013, "CTX LICENSE NOT AVAILABLE"}, \ + {0xC00A0014, "CTX LICENSE EXPIRED"}, \ + {0xC00A0015, "CTX WINSTATION NOT FOUND"}, \ + {0xC00A0016, "CTX WINSTATION NAME COLLISION"}, \ + {0xC00A0017, "CTX WINSTATION BUSY"}, \ + {0xC00A0018, "CTX BAD VIDEO MODE"}, \ + {0xC00A0022, "CTX GRAPHICS INVALID"}, \ + {0xC00A0024, "CTX NOT CONSOLE"}, \ + {0xC00A0026, "CTX CLIENT QUERY TIMEOUT"}, \ + {0xC00A0027, "CTX CONSOLE DISCONNECT"}, \ + {0xC00A0028, "CTX CONSOLE CONNECT"}, \ + {0xC00A002A, "CTX SHADOW DENIED"}, \ + {0xC00A002B, "CTX WINSTATION ACCESS DENIED"}, \ + {0xC00A002E, "CTX INVALID WD"}, \ + {0xC00A002F, "CTX WD NOT FOUND"}, \ + {0xC00A0030, "CTX SHADOW INVALID"}, \ + {0xC00A0031, "CTX SHADOW DISABLED"}, \ + {0xC00A0032, "RDP PROTOCOL ERROR"}, \ + {0xC00A0033, "CTX CLIENT LICENSE NOT SET"}, \ + {0xC00A0034, "CTX CLIENT LICENSE IN USE"}, \ + {0xC00A0035, "CTX SHADOW ENDED BY MODE CHANGE"}, \ + {0xC00A0036, "CTX SHADOW NOT RUNNING"}, \ + {0xC0130001, "CLUSTER INVALID NODE"}, \ + {0xC0130002, "CLUSTER NODE EXISTS"}, \ + {0xC0130003, "CLUSTER JOIN IN PROGRESS"}, \ + {0xC0130004, "CLUSTER NODE NOT FOUND"}, \ + {0xC0130005, "CLUSTER LOCAL NODE NOT FOUND"}, \ + {0xC0130006, "CLUSTER NETWORK EXISTS"}, \ + {0xC0130007, "CLUSTER NETWORK NOT FOUND"}, \ + {0xC0130008, "CLUSTER NETINTERFACE EXISTS"}, \ + {0xC0130009, "CLUSTER NETINTERFACE NOT FOUND"}, \ + {0xC013000A, "CLUSTER INVALID REQUEST"}, \ + {0xC013000B, "CLUSTER INVALID NETWORK PROVIDER"}, \ + {0xC013000C, "CLUSTER NODE DOWN"}, \ + {0xC013000D, "CLUSTER NODE UNREACHABLE"}, \ + {0xC013000E, "CLUSTER NODE NOT MEMBER"}, \ + {0xC013000F, "CLUSTER JOIN NOT IN PROGRESS"}, \ + {0xC0130010, "CLUSTER INVALID NETWORK"}, \ + {0xC0130011, "CLUSTER NO NET ADAPTERS"}, \ + {0xC0130012, "CLUSTER NODE UP"}, \ + {0xC0130013, "CLUSTER NODE PAUSED"}, \ + {0xC0130014, "CLUSTER NODE NOT PAUSED"}, \ + {0xC0130015, "CLUSTER NO SECURITY CONTEXT"}, \ + {0xC0130016, "CLUSTER NETWORK NOT INTERNAL"}, \ + {0xC0130017, "CLUSTER POISONED"}, \ + {0xC0150001, "SXS SECTION NOT FOUND"}, \ + {0xC0150002, "SXS CANT GEN ACTCTX"}, \ + {0xC0150003, "SXS INVALID ACTCTXDATA FORMAT"}, \ + {0xC0150004, "SXS ASSEMBLY NOT FOUND"}, \ + {0xC0150005, "SXS MANIFEST FORMAT ERROR"}, \ + {0xC0150006, "SXS MANIFEST PARSE ERROR"}, \ + {0xC0150007, "SXS ACTIVATION CONTEXT DISABLED"}, \ + {0xC0150008, "SXS KEY NOT FOUND"}, \ + {0xC0150009, "SXS VERSION CONFLICT"}, \ + {0xC015000A, "SXS WRONG SECTION TYPE"}, \ + {0xC015000B, "SXS THREAD QUERIES DISABLED"}, \ + {0xC015000C, "SXS ASSEMBLY MISSING"}, \ + {0xC015000E, "SXS PROCESS DEFAULT ALREADY SET"}, \ + {0xC015000F, "SXS EARLY DEACTIVATION"}, \ + {0xC0150010, "SXS INVALID DEACTIVATION"}, \ + {0xC0150011, "SXS MULTIPLE DEACTIVATION"}, \ + {0xC0150012, "SXS SYSTEM DEFAULT ACTIVATION CONTEXT EMPTY"}, \ + {0xC0150013, "SXS PROCESS TERMINATION REQUESTED"}, \ + {0xC0150014, "SXS CORRUPT ACTIVATION STACK"}, \ + {0xC0150015, "SXS CORRUPTION"}, \ +} + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/ntstatus.h posixrdp/posixxrdp.orig/common/ntstatus.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/ntstatus.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/ntstatus.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,1994 @@ +/* + * Win32 definitions for Windows NT + * + * Copyright 1996 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _NTSTATUS_ +#define _NTSTATUS_ + +#ifndef WIN32_NO_STATUS + +/* + * Debug codes + */ + +#define DBG_EXCEPTION_HANDLED 0x00010001 +#define DBG_CONTINUE 0x00010002 +#define DBG_REPLY_LATER 0x40010001 +#define DBG_UNABLE_TO_PROVIDE_HANDLE 0x40010002 +#define DBG_TERMINATE_THREAD 0x40010003 +#define DBG_TERMINATE_PROCESS 0x40010004 +#define DBG_CONTROL_C 0x40010005 +#define DBG_PRINTEXCEPTION_C 0x40010006 +#define DBG_RIPEXCEPTION 0x40010007 +#define DBG_CONTROL_BREAK 0x40010008 +#define DBG_COMMAND_EXCEPTION 0x40010009 +#define DBG_EXCEPTION_NOT_HANDLED 0x80010001 +#define DBG_NO_STATE_CHANGE 0xC0010001 +#define DBG_APP_NOT_IDLE 0xC0010002 + +/* + * Exception codes + */ + +#define STATUS_SUCCESS 0x0 +#define STATUS_SEVERITY_SUCCESS 0x0 +#define STATUS_SEVERITY_INFORMATIONAL 0x1 +#define STATUS_SEVERITY_WARNING 0x2 +#define STATUS_SEVERITY_ERROR 0x3 + +#define STATUS_WAIT_1 0x00000001 +#define STATUS_WAIT_2 0x00000002 +#define STATUS_WAIT_3 0x00000003 +#define STATUS_WAIT_63 0x0000003f +#define STATUS_ABANDONED 0x00000080 +#define STATUS_ABANDONED_WAIT_63 0x000000BF +#define STATUS_KERNEL_APC 0x00000100 +#define STATUS_ALERTED 0x00000101 +#define STATUS_TIMEOUT 0x00000102 +#define STATUS_PENDING 0x00000103 +#define STATUS_REPARSE 0x00000104 +#define STATUS_MORE_ENTRIES 0x00000105 +#define STATUS_NOT_ALL_ASSIGNED 0x00000106 +#define STATUS_SOME_NOT_MAPPED 0x00000107 +#define STATUS_OPLOCK_BREAK_IN_PROGRESS 0x00000108 +#define STATUS_VOLUME_MOUNTED 0x00000109 +#define STATUS_RXACT_COMMITTED 0x0000010A +#define STATUS_NOTIFY_CLEANUP 0x0000010B +#define STATUS_NOTIFY_ENUM_DIR 0x0000010C +#define STATUS_NO_QUOTAS_FOR_ACCOUNT 0x0000010D +#define STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED 0x0000010E +#define STATUS_PAGE_FAULT_TRANSITION 0x00000110 +#define STATUS_PAGE_FAULT_DEMAND_ZERO 0x00000111 +#define STATUS_PAGE_FAULT_COPY_ON_WRITE 0x00000112 +#define STATUS_PAGE_FAULT_GUARD_PAGE 0x00000113 +#define STATUS_PAGE_FAULT_PAGING_FILE 0x00000114 +#define STATUS_CACHE_PAGE_LOCKED 0x00000115 +#define STATUS_CRASH_DUMP 0x00000116 +#define STATUS_BUFFER_ALL_ZEROS 0x00000117 +#define STATUS_REPARSE_OBJECT 0x00000118 +#define STATUS_RESOURCE_REQUIREMENTS_CHANGED 0x00000119 +#define STATUS_TRANSLATION_COMPLETE 0x00000120 +#define STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY 0x00000121 +#define STATUS_NOTHING_TO_TERMINATE 0x00000122 +#define STATUS_PROCESS_NOT_IN_JOB 0x00000123 +#define STATUS_PROCESS_IN_JOB 0x00000124 +#define STATUS_VOLSNAP_HIBERNATE_READY 0x00000125 +#define STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY 0x00000126 + +#define STATUS_OBJECT_NAME_EXISTS 0x40000000 +#define STATUS_THREAD_WAS_SUSPENDED 0x40000001 +#define STATUS_WORKING_SET_LIMIT_RANGE 0x40000002 +#define STATUS_IMAGE_NOT_AT_BASE 0x40000003 +#define STATUS_RXACT_STATE_CREATED 0x40000004 +#define STATUS_SEGMENT_NOTIFICATION 0x40000005 +#define STATUS_LOCAL_USER_SESSION_KEY 0x40000006 +#define STATUS_BAD_CURRENT_DIRECTORY 0x40000007 +#define STATUS_SERIAL_MORE_WRITES 0x40000008 +#define STATUS_REGISTRY_RECOVERED 0x40000009 +#define STATUS_FT_READ_RECOVERY_FROM_BACKUP 0x4000000A +#define STATUS_FT_WRITE_RECOVERY 0x4000000B +#define STATUS_SERIAL_COUNTER_TIMEOUT 0x4000000C +#define STATUS_NULL_LM_PASSWORD 0x4000000D +#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH 0x4000000E +#define STATUS_RECEIVE_PARTIAL 0x4000000F +#define STATUS_RECEIVE_EXPEDITED 0x40000010 +#define STATUS_RECEIVE_PARTIAL_EXPEDITED 0x40000011 +#define STATUS_EVENT_DONE 0x40000012 +#define STATUS_EVENT_PENDING 0x40000013 +#define STATUS_CHECKING_FILE_SYSTEM 0x40000014 +#define STATUS_FATAL_APP_EXIT 0x40000015 +#define STATUS_PREDEFINED_HANDLE 0x40000016 +#define STATUS_WAS_UNLOCKED 0x40000017 +#define STATUS_SERVICE_NOTIFICATION 0x40000018 +#define STATUS_WAS_LOCKED 0x40000019 +#define STATUS_LOG_HARD_ERROR 0x4000001A +#define STATUS_ALREADY_WIN32 0x4000001B +#define STATUS_WX86_UNSIMULATE 0x4000001C +#define STATUS_WX86_CONTINUE 0x4000001D +#define STATUS_WX86_SINGLE_STEP 0x4000001E +#define STATUS_WX86_BREAKPOINT 0x4000001F +#define STATUS_WX86_EXCEPTION_CONTINUE 0x40000020 +#define STATUS_WX86_EXCEPTION_LASTCHANCE 0x40000021 +#define STATUS_WX86_EXCEPTION_CHAIN 0x40000022 +#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE 0x40000023 +#define STATUS_NO_YIELD_PERFORMED 0x40000024 +#define STATUS_TIMER_RESUME_IGNORED 0x40000025 +#define STATUS_ARBITRATION_UNHANDLED 0x40000026 +#define STATUS_CARDBUS_NOT_SUPPORTED 0x40000027 +#define STATUS_WX86_CREATEWX86TIB 0x40000028 +#define STATUS_MP_PROCESSOR_MISMATCH 0x40000029 +#define STATUS_HIBERNATED 0x4000002A +#define STATUS_RESUME_HIBERNATION 0x4000002B +#define STATUS_FIRMWARE_UPDATED 0x4000002C +#define STATUS_WAKE_SYSTEM 0x40000294 +#define STATUS_DS_SHUTTING_DOWN 0x40000370 + +#define RPC_NT_UUID_LOCAL_ONLY 0x40020056 +#define RPC_NT_SEND_INCOMPLETE 0x400200AF + +#define STATUS_CTX_CDM_CONNECT 0x400A0004 +#define STATUS_CTX_CDM_DISCONNECT 0x400A0005 + +#define STATUS_SXS_RELEASE_ACTIVATION_CONTEXT 0x4015000D + +#define STATUS_GUARD_PAGE_VIOLATION 0x80000001 +#define STATUS_DATATYPE_MISALIGNMENT 0x80000002 +#define STATUS_BREAKPOINT 0x80000003 +#define STATUS_SINGLE_STEP 0x80000004 +#define STATUS_BUFFER_OVERFLOW 0x80000005 +#define STATUS_NO_MORE_FILES 0x80000006 +#define STATUS_WAKE_SYSTEM_DEBUGGER 0x80000007 + +#define STATUS_HANDLES_CLOSED 0x8000000A +#define STATUS_NO_INHERITANCE 0x8000000B +#define STATUS_GUID_SUBSTITUTION_MADE 0x8000000C +#define STATUS_PARTIAL_COPY 0x8000000D +#define STATUS_DEVICE_PAPER_EMPTY 0x8000000E +#define STATUS_DEVICE_POWERED_OFF 0x8000000F +#define STATUS_DEVICE_OFF_LINE 0x80000010 +#define STATUS_DEVICE_BUSY 0x80000011 +#define STATUS_NO_MORE_EAS 0x80000012 +#define STATUS_INVALID_EA_NAME 0x80000013 +#define STATUS_EA_LIST_INCONSISTENT 0x80000014 +#define STATUS_INVALID_EA_FLAG 0x80000015 +#define STATUS_VERIFY_REQUIRED 0x80000016 +#define STATUS_EXTRANEOUS_INFORMATION 0x80000017 +#define STATUS_RXACT_COMMIT_NECESSARY 0x80000018 +#define STATUS_NO_MORE_ENTRIES 0x8000001A +#define STATUS_FILEMARK_DETECTED 0x8000001B +#define STATUS_MEDIA_CHANGED 0x8000001C +#define STATUS_BUS_RESET 0x8000001D +#define STATUS_END_OF_MEDIA 0x8000001E +#define STATUS_BEGINNING_OF_MEDIA 0x8000001F +#define STATUS_MEDIA_CHECK 0x80000020 +#define STATUS_SETMARK_DETECTED 0x80000021 +#define STATUS_NO_DATA_DETECTED 0x80000022 +#define STATUS_REDIRECTOR_HAS_OPEN_HANDLES 0x80000023 +#define STATUS_SERVER_HAS_OPEN_HANDLES 0x80000024 +#define STATUS_ALREADY_DISCONNECTED 0x80000025 +#define STATUS_LONGJUMP 0x80000026 +#define STATUS_CLEANER_CARTRIDGE_INSTALLED 0x80000027 +#define STATUS_PLUGPLAY_QUERY_VETOED 0x80000028 +#define STATUS_UNWIND_CONSOLIDATE 0x80000029 +#define STATUS_REGISTRY_HIVE_RECOVERED 0x8000002A +#define STATUS_DLL_MIGHT_BE_INSECURE 0x8000002B +#define STATUS_DLL_MIGHT_BE_INCOMPATIBLE 0x8000002C + +#define STATUS_DEVICE_REQUIRES_CLEANING 0x80000288 +#define STATUS_DEVICE_DOOR_OPEN 0x80000289 + +#define STATUS_CLUSTER_NODE_ALREADY_UP 0x80130001 +#define STATUS_CLUSTER_NODE_ALREADY_DOWN 0x80130002 +#define STATUS_CLUSTER_NETWORK_ALREADY_ONLINE 0x80130003 +#define STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE 0x80130004 +#define STATUS_CLUSTER_NODE_ALREADY_MEMBER 0x80130005 + +#define STATUS_WAIT_0 0x00000000 +#define STATUS_UNSUCCESSFUL 0xC0000001 +#define STATUS_NOT_IMPLEMENTED 0xC0000002 +#define STATUS_INVALID_INFO_CLASS 0xC0000003 +#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004 +#define STATUS_ACCESS_VIOLATION 0xC0000005 +#define STATUS_IN_PAGE_ERROR 0xC0000006 +#define STATUS_PAGEFILE_QUOTA 0xC0000007 +#define STATUS_INVALID_HANDLE 0xC0000008 +#define STATUS_BAD_INITIAL_STACK 0xC0000009 +#define STATUS_BAD_INITIAL_PC 0xC000000A +#define STATUS_INVALID_CID 0xC000000B +#define STATUS_TIMER_NOT_CANCELED 0xC000000C +#define STATUS_INVALID_PARAMETER 0xC000000D +#define STATUS_NO_SUCH_DEVICE 0xC000000E +#define STATUS_NO_SUCH_FILE 0xC000000F +#define STATUS_INVALID_DEVICE_REQUEST 0xC0000010 +#define STATUS_END_OF_FILE 0xC0000011 +#define STATUS_WRONG_VOLUME 0xC0000012 +#define STATUS_NO_MEDIA_IN_DEVICE 0xC0000013 +#define STATUS_UNRECOGNIZED_MEDIA 0xC0000014 +#define STATUS_NONEXISTENT_SECTOR 0xC0000015 +#define STATUS_MORE_PROCESSING_REQUIRED 0xC0000016 +#define STATUS_NO_MEMORY 0xC0000017 +#define STATUS_CONFLICTING_ADDRESSES 0xC0000018 +#define STATUS_NOT_MAPPED_VIEW 0xC0000019 +#define STATUS_UNABLE_TO_FREE_VM 0xC000001A +#define STATUS_UNABLE_TO_DELETE_SECTION 0xC000001B +#define STATUS_INVALID_SYSTEM_SERVICE 0xC000001C +#define STATUS_ILLEGAL_INSTRUCTION 0xC000001D +#define STATUS_INVALID_LOCK_SEQUENCE 0xC000001E +#define STATUS_INVALID_VIEW_SIZE 0xC000001F +#define STATUS_INVALID_FILE_FOR_SECTION 0xC0000020 +#define STATUS_ALREADY_COMMITTED 0xC0000021 +#define STATUS_ACCESS_DENIED 0xC0000022 +#define STATUS_BUFFER_TOO_SMALL 0xC0000023 +#define STATUS_OBJECT_TYPE_MISMATCH 0xC0000024 +#define STATUS_NONCONTINUABLE_EXCEPTION 0xC0000025 +#define STATUS_INVALID_DISPOSITION 0xC0000026 +#define STATUS_UNWIND 0xC0000027 +#define STATUS_BAD_STACK 0xC0000028 +#define STATUS_INVALID_UNWIND_TARGET 0xC0000029 +#define STATUS_NOT_LOCKED 0xC000002A +#define STATUS_PARITY_ERROR 0xC000002B +#define STATUS_UNABLE_TO_DECOMMIT_VM 0xC000002C +#define STATUS_NOT_COMMITTED 0xC000002D +#define STATUS_INVALID_PORT_ATTRIBUTES 0xC000002E +#define STATUS_PORT_MESSAGE_TOO_LONG 0xC000002F +#define STATUS_INVALID_PARAMETER_MIX 0xC0000030 +#define STATUS_INVALID_QUOTA_LOWER 0xC0000031 +#define STATUS_DISK_CORRUPT_ERROR 0xC0000032 +#define STATUS_OBJECT_NAME_INVALID 0xC0000033 +#define STATUS_OBJECT_NAME_NOT_FOUND 0xC0000034 +#define STATUS_OBJECT_NAME_COLLISION 0xC0000035 +#define STATUS_PORT_DISCONNECTED 0xC0000037 +#define STATUS_DEVICE_ALREADY_ATTACHED 0xC0000038 +#define STATUS_OBJECT_PATH_INVALID 0xC0000039 +#define STATUS_OBJECT_PATH_NOT_FOUND 0xC000003A +#define STATUS_OBJECT_PATH_SYNTAX_BAD 0xC000003B +#define STATUS_DATA_OVERRUN 0xC000003C +#define STATUS_DATA_LATE_ERROR 0xC000003D +#define STATUS_DATA_ERROR 0xC000003E +#define STATUS_CRC_ERROR 0xC000003F +#define STATUS_SECTION_TOO_BIG 0xC0000040 +#define STATUS_PORT_CONNECTION_REFUSED 0xC0000041 +#define STATUS_INVALID_PORT_HANDLE 0xC0000042 +#define STATUS_SHARING_VIOLATION 0xC0000043 +#define STATUS_QUOTA_EXCEEDED 0xC0000044 +#define STATUS_INVALID_PAGE_PROTECTION 0xC0000045 +#define STATUS_MUTANT_NOT_OWNED 0xC0000046 +#define STATUS_SEMAPHORE_LIMIT_EXCEEDED 0xC0000047 +#define STATUS_PORT_ALREADY_SET 0xC0000048 +#define STATUS_SECTION_NOT_IMAGE 0xC0000049 +#define STATUS_SUSPEND_COUNT_EXCEEDED 0xC000004A +#define STATUS_THREAD_IS_TERMINATING 0xC000004B +#define STATUS_BAD_WORKING_SET_LIMIT 0xC000004C +#define STATUS_INCOMPATIBLE_FILE_MAP 0xC000004D +#define STATUS_SECTION_PROTECTION 0xC000004E +#define STATUS_EAS_NOT_SUPPORTED 0xC000004F +#define STATUS_EA_TOO_LARGE 0xC0000050 +#define STATUS_NONEXISTENT_EA_ENTRY 0xC0000051 +#define STATUS_NO_EAS_ON_FILE 0xC0000052 +#define STATUS_EA_CORRUPT_ERROR 0xC0000053 +#define STATUS_FILE_LOCK_CONFLICT 0xC0000054 +#define STATUS_LOCK_NOT_GRANTED 0xC0000055 +#define STATUS_DELETE_PENDING 0xC0000056 +#define STATUS_CTL_FILE_NOT_SUPPORTED 0xC0000057 +#define STATUS_UNKNOWN_REVISION 0xC0000058 +#define STATUS_REVISION_MISMATCH 0xC0000059 +#define STATUS_INVALID_OWNER 0xC000005A +#define STATUS_INVALID_PRIMARY_GROUP 0xC000005B +#define STATUS_NO_IMPERSONATION_TOKEN 0xC000005C +#define STATUS_CANT_DISABLE_MANDATORY 0xC000005D +#define STATUS_NO_LOGON_SERVERS 0xC000005E +#define STATUS_NO_SUCH_LOGON_SESSION 0xC000005F +#define STATUS_NO_SUCH_PRIVILEGE 0xC0000060 +#define STATUS_PRIVILEGE_NOT_HELD 0xC0000061 +#define STATUS_INVALID_ACCOUNT_NAME 0xC0000062 +#define STATUS_USER_EXISTS 0xC0000063 +#define STATUS_NO_SUCH_USER 0xC0000064 +#define STATUS_GROUP_EXISTS 0xC0000065 +#define STATUS_NO_SUCH_GROUP 0xC0000066 +#define STATUS_MEMBER_IN_GROUP 0xC0000067 +#define STATUS_MEMBER_NOT_IN_GROUP 0xC0000068 +#define STATUS_LAST_ADMIN 0xC0000069 +#define STATUS_WRONG_PASSWORD 0xC000006A +#define STATUS_ILL_FORMED_PASSWORD 0xC000006B +#define STATUS_PASSWORD_RESTRICTION 0xC000006C +#define STATUS_LOGON_FAILURE 0xC000006D +#define STATUS_ACCOUNT_RESTRICTION 0xC000006E +#define STATUS_INVALID_LOGON_HOURS 0xC000006F +#define STATUS_INVALID_WORKSTATION 0xC0000070 +#define STATUS_PASSWORD_EXPIRED 0xC0000071 +#define STATUS_ACCOUNT_DISABLED 0xC0000072 +#define STATUS_NONE_MAPPED 0xC0000073 +#define STATUS_TOO_MANY_LUIDS_REQUESTED 0xC0000074 +#define STATUS_LUIDS_EXHAUSTED 0xC0000075 +#define STATUS_INVALID_SUB_AUTHORITY 0xC0000076 +#define STATUS_INVALID_ACL 0xC0000077 +#define STATUS_INVALID_SID 0xC0000078 +#define STATUS_INVALID_SECURITY_DESCR 0xC0000079 +#define STATUS_PROCEDURE_NOT_FOUND 0xC000007A +#define STATUS_INVALID_IMAGE_FORMAT 0xC000007B +#define STATUS_NO_TOKEN 0xC000007C +#define STATUS_BAD_INHERITANCE_ACL 0xC000007D +#define STATUS_RANGE_NOT_LOCKED 0xC000007E +#define STATUS_DISK_FULL 0xC000007F +#define STATUS_SERVER_DISABLED 0xC0000080 +#define STATUS_SERVER_NOT_DISABLED 0xC0000081 +#define STATUS_TOO_MANY_GUIDS_REQUESTED 0xC0000082 +#define STATUS_GUIDS_EXHAUSTED 0xC0000083 +#define STATUS_INVALID_ID_AUTHORITY 0xC0000084 +#define STATUS_AGENTS_EXHAUSTED 0xC0000085 +#define STATUS_INVALID_VOLUME_LABEL 0xC0000086 +#define STATUS_SECTION_NOT_EXTENDED 0xC0000087 +#define STATUS_NOT_MAPPED_DATA 0xC0000088 +#define STATUS_RESOURCE_DATA_NOT_FOUND 0xC0000089 +#define STATUS_RESOURCE_TYPE_NOT_FOUND 0xC000008A +#define STATUS_RESOURCE_NAME_NOT_FOUND 0xC000008B +#define STATUS_ARRAY_BOUNDS_EXCEEDED 0xC000008C +#define STATUS_FLOAT_DENORMAL_OPERAND 0xC000008D +#define STATUS_FLOAT_DIVIDE_BY_ZERO 0xC000008E +#define STATUS_FLOAT_INEXACT_RESULT 0xC000008F +#define STATUS_FLOAT_INVALID_OPERATION 0xC0000090 +#define STATUS_FLOAT_OVERFLOW 0xC0000091 +#define STATUS_FLOAT_STACK_CHECK 0xC0000092 +#define STATUS_FLOAT_UNDERFLOW 0xC0000093 +#define STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000094 +#define STATUS_INTEGER_OVERFLOW 0xC0000095 +#define STATUS_PRIVILEGED_INSTRUCTION 0xC0000096 +#define STATUS_TOO_MANY_PAGING_FILES 0xC0000097 +#define STATUS_FILE_INVALID 0xC0000098 +#define STATUS_ALLOTTED_SPACE_EXCEEDED 0xC0000099 +#define STATUS_INSUFFICIENT_RESOURCES 0xC000009A +#define STATUS_DFS_EXIT_PATH_FOUND 0xC000009B +#define STATUS_DEVICE_DATA_ERROR 0xC000009C +#define STATUS_DEVICE_NOT_CONNECTED 0xC000009D +#define STATUS_DEVICE_POWER_FAILURE 0xC000009E +#define STATUS_FREE_VM_NOT_AT_BASE 0xC000009F +#define STATUS_MEMORY_NOT_ALLOCATED 0xC00000A0 +#define STATUS_WORKING_SET_QUOTA 0xC00000A1 +#define STATUS_MEDIA_WRITE_PROTECTED 0xC00000A2 +#define STATUS_DEVICE_NOT_READY 0xC00000A3 +#define STATUS_INVALID_GROUP_ATTRIBUTES 0xC00000A4 +#define STATUS_BAD_IMPERSONATION_LEVEL 0xC00000A5 +#define STATUS_CANT_OPEN_ANONYMOUS 0xC00000A6 +#define STATUS_BAD_VALIDATION_CLASS 0xC00000A7 +#define STATUS_BAD_TOKEN_TYPE 0xC00000A8 +#define STATUS_BAD_MASTER_BOOT_RECORD 0xC00000A9 +#define STATUS_INSTRUCTION_MISALIGNMENT 0xC00000AA +#define STATUS_INSTANCE_NOT_AVAILABLE 0xC00000AB +#define STATUS_PIPE_NOT_AVAILABLE 0xC00000AC +#define STATUS_INVALID_PIPE_STATE 0xC00000AD +#define STATUS_PIPE_BUSY 0xC00000AE +#define STATUS_ILLEGAL_FUNCTION 0xC00000AF +#define STATUS_PIPE_DISCONNECTED 0xC00000B0 +#define STATUS_PIPE_CLOSING 0xC00000B1 +#define STATUS_PIPE_CONNECTED 0xC00000B2 +#define STATUS_PIPE_LISTENING 0xC00000B3 +#define STATUS_INVALID_READ_MODE 0xC00000B4 +#define STATUS_IO_TIMEOUT 0xC00000B5 +#define STATUS_FILE_FORCED_CLOSED 0xC00000B6 +#define STATUS_PROFILING_NOT_STARTED 0xC00000B7 +#define STATUS_PROFILING_NOT_STOPPED 0xC00000B8 +#define STATUS_COULD_NOT_INTERPRET 0xC00000B9 +#define STATUS_FILE_IS_A_DIRECTORY 0xC00000BA +#define STATUS_NOT_SUPPORTED 0xC00000BB +#define STATUS_REMOTE_NOT_LISTENING 0xC00000BC +#define STATUS_DUPLICATE_NAME 0xC00000BD +#define STATUS_BAD_NETWORK_PATH 0xC00000BE +#define STATUS_NETWORK_BUSY 0xC00000BF +#define STATUS_DEVICE_DOES_NOT_EXIST 0xC00000C0 +#define STATUS_TOO_MANY_COMMANDS 0xC00000C1 +#define STATUS_ADAPTER_HARDWARE_ERROR 0xC00000C2 +#define STATUS_INVALID_NETWORK_RESPONSE 0xC00000C3 +#define STATUS_UNEXPECTED_NETWORK_ERROR 0xC00000C4 +#define STATUS_BAD_REMOTE_ADAPTER 0xC00000C5 +#define STATUS_PRINT_QUEUE_FULL 0xC00000C6 +#define STATUS_NO_SPOOL_SPACE 0xC00000C7 +#define STATUS_PRINT_CANCELLED 0xC00000C8 +#define STATUS_NETWORK_NAME_DELETED 0xC00000C9 +#define STATUS_NETWORK_ACCESS_DENIED 0xC00000CA +#define STATUS_BAD_DEVICE_TYPE 0xC00000CB +#define STATUS_BAD_NETWORK_NAME 0xC00000CC +#define STATUS_TOO_MANY_NAMES 0xC00000CD +#define STATUS_TOO_MANY_SESSIONS 0xC00000CE +#define STATUS_SHARING_PAUSED 0xC00000CF +#define STATUS_REQUEST_NOT_ACCEPTED 0xC00000D0 +#define STATUS_REDIRECTOR_PAUSED 0xC00000D1 +#define STATUS_NET_WRITE_FAULT 0xC00000D2 +#define STATUS_PROFILING_AT_LIMIT 0xC00000D3 +#define STATUS_NOT_SAME_DEVICE 0xC00000D4 +#define STATUS_FILE_RENAMED 0xC00000D5 +#define STATUS_VIRTUAL_CIRCUIT_CLOSED 0xC00000D6 +#define STATUS_NO_SECURITY_ON_OBJECT 0xC00000D7 +#define STATUS_CANT_WAIT 0xC00000D8 +#define STATUS_PIPE_EMPTY 0xC00000D9 +#define STATUS_CANT_ACCESS_DOMAIN_INFO 0xC00000DA +#define STATUS_CANT_TERMINATE_SELF 0xC00000DB +#define STATUS_INVALID_SERVER_STATE 0xC00000DC +#define STATUS_INVALID_DOMAIN_STATE 0xC00000DD +#define STATUS_INVALID_DOMAIN_ROLE 0xC00000DE +#define STATUS_NO_SUCH_DOMAIN 0xC00000DF +#define STATUS_DOMAIN_EXISTS 0xC00000E0 +#define STATUS_DOMAIN_LIMIT_EXCEEDED 0xC00000E1 +#define STATUS_OPLOCK_NOT_GRANTED 0xC00000E2 +#define STATUS_INVALID_OPLOCK_PROTOCOL 0xC00000E3 +#define STATUS_INTERNAL_DB_CORRUPTION 0xC00000E4 +#define STATUS_INTERNAL_ERROR 0xC00000E5 +#define STATUS_GENERIC_NOT_MAPPED 0xC00000E6 +#define STATUS_BAD_DESCRIPTOR_FORMAT 0xC00000E7 +#define STATUS_INVALID_USER_BUFFER 0xC00000E8 +#define STATUS_UNEXPECTED_IO_ERROR 0xC00000E9 +#define STATUS_UNEXPECTED_MM_CREATE_ERR 0xC00000EA +#define STATUS_UNEXPECTED_MM_MAP_ERROR 0xC00000EB +#define STATUS_UNEXPECTED_MM_EXTEND_ERR 0xC00000EC +#define STATUS_NOT_LOGON_PROCESS 0xC00000ED +#define STATUS_LOGON_SESSION_EXISTS 0xC00000EE +#define STATUS_INVALID_PARAMETER_1 0xC00000EF +#define STATUS_INVALID_PARAMETER_2 0xC00000F0 +#define STATUS_INVALID_PARAMETER_3 0xC00000F1 +#define STATUS_INVALID_PARAMETER_4 0xC00000F2 +#define STATUS_INVALID_PARAMETER_5 0xC00000F3 +#define STATUS_INVALID_PARAMETER_6 0xC00000F4 +#define STATUS_INVALID_PARAMETER_7 0xC00000F5 +#define STATUS_INVALID_PARAMETER_8 0xC00000F6 +#define STATUS_INVALID_PARAMETER_9 0xC00000F7 +#define STATUS_INVALID_PARAMETER_10 0xC00000F8 +#define STATUS_INVALID_PARAMETER_11 0xC00000F9 +#define STATUS_INVALID_PARAMETER_12 0xC00000FA +#define STATUS_REDIRECTOR_NOT_STARTED 0xC00000FB +#define STATUS_REDIRECTOR_STARTED 0xC00000FC +#define STATUS_STACK_OVERFLOW 0xC00000FD +#define STATUS_NO_SUCH_PACKAGE 0xC00000FE +#define STATUS_BAD_FUNCTION_TABLE 0xC00000FF +#define STATUS_VARIABLE_NOT_FOUND 0xC0000100 +#define STATUS_DIRECTORY_NOT_EMPTY 0xC0000101 +#define STATUS_FILE_CORRUPT_ERROR 0xC0000102 +#define STATUS_NOT_A_DIRECTORY 0xC0000103 +#define STATUS_BAD_LOGON_SESSION_STATE 0xC0000104 +#define STATUS_LOGON_SESSION_COLLISION 0xC0000105 +#define STATUS_NAME_TOO_LONG 0xC0000106 +#define STATUS_FILES_OPEN 0xC0000107 +#define STATUS_CONNECTION_IN_USE 0xC0000108 +#define STATUS_MESSAGE_NOT_FOUND 0xC0000109 +#define STATUS_PROCESS_IS_TERMINATING 0xC000010A +#define STATUS_INVALID_LOGON_TYPE 0xC000010B +#define STATUS_NO_GUID_TRANSLATION 0xC000010C +#define STATUS_CANNOT_IMPERSONATE 0xC000010D +#define STATUS_IMAGE_ALREADY_LOADED 0xC000010E +#define STATUS_ABIOS_NOT_PRESENT 0xC000010F +#define STATUS_ABIOS_LID_NOT_EXIST 0xC0000110 +#define STATUS_ABIOS_LID_ALREADY_OWNED 0xC0000111 +#define STATUS_ABIOS_NOT_LID_OWNER 0xC0000112 +#define STATUS_ABIOS_INVALID_COMMAND 0xC0000113 +#define STATUS_ABIOS_INVALID_LID 0xC0000114 +#define STATUS_ABIOS_SELECTOR_NOT_AVAILABLE 0xC0000115 +#define STATUS_ABIOS_INVALID_SELECTOR 0xC0000116 +#define STATUS_NO_LDT 0xC0000117 +#define STATUS_INVALID_LDT_SIZE 0xC0000118 +#define STATUS_INVALID_LDT_OFFSET 0xC0000119 +#define STATUS_INVALID_LDT_DESCRIPTOR 0xC000011A +#define STATUS_INVALID_IMAGE_NE_FORMAT 0xC000011B +#define STATUS_RXACT_INVALID_STATE 0xC000011C +#define STATUS_RXACT_COMMIT_FAILURE 0xC000011D +#define STATUS_MAPPED_FILE_SIZE_ZERO 0xC000011E +#define STATUS_TOO_MANY_OPENED_FILES 0xC000011F +#define STATUS_CANCELLED 0xC0000120 +#define STATUS_CANNOT_DELETE 0xC0000121 +#define STATUS_INVALID_COMPUTER_NAME 0xC0000122 +#define STATUS_FILE_DELETED 0xC0000123 +#define STATUS_SPECIAL_ACCOUNT 0xC0000124 +#define STATUS_SPECIAL_GROUP 0xC0000125 +#define STATUS_SPECIAL_USER 0xC0000126 +#define STATUS_MEMBERS_PRIMARY_GROUP 0xC0000127 +#define STATUS_FILE_CLOSED 0xC0000128 +#define STATUS_TOO_MANY_THREADS 0xC0000129 +#define STATUS_THREAD_NOT_IN_PROCESS 0xC000012A +#define STATUS_TOKEN_ALREADY_IN_USE 0xC000012B +#define STATUS_PAGEFILE_QUOTA_EXCEEDED 0xC000012C +#define STATUS_COMMITMENT_LIMIT 0xC000012D +#define STATUS_INVALID_IMAGE_LE_FORMAT 0xC000012E +#define STATUS_INVALID_IMAGE_NOT_MZ 0xC000012F +#define STATUS_INVALID_IMAGE_PROTECT 0xC0000130 +#define STATUS_INVALID_IMAGE_WIN_16 0xC0000131 +#define STATUS_LOGON_SERVER_CONFLICT 0xC0000132 +#define STATUS_TIME_DIFFERENCE_AT_DC 0xC0000133 +#define STATUS_SYNCHRONIZATION_REQUIRED 0xC0000134 +#define STATUS_DLL_NOT_FOUND 0xC0000135 +#define STATUS_OPEN_FAILED 0xC0000136 +#define STATUS_IO_PRIVILEGE_FAILED 0xC0000137 +#define STATUS_ORDINAL_NOT_FOUND 0xC0000138 +#define STATUS_ENTRYPOINT_NOT_FOUND 0xC0000139 +#define STATUS_CONTROL_C_EXIT 0xC000013A +#define STATUS_LOCAL_DISCONNECT 0xC000013B +#define STATUS_REMOTE_DISCONNECT 0xC000013C +#define STATUS_REMOTE_RESOURCES 0xC000013D +#define STATUS_LINK_FAILED 0xC000013E +#define STATUS_LINK_TIMEOUT 0xC000013F +#define STATUS_INVALID_CONNECTION 0xC0000140 +#define STATUS_INVALID_ADDRESS 0xC0000141 +#define STATUS_DLL_INIT_FAILED 0xC0000142 +#define STATUS_MISSING_SYSTEMFILE 0xC0000143 +#define STATUS_UNHANDLED_EXCEPTION 0xC0000144 +#define STATUS_APP_INIT_FAILURE 0xC0000145 +#define STATUS_PAGEFILE_CREATE_FAILED 0xC0000146 +#define STATUS_NO_PAGEFILE 0xC0000147 +#define STATUS_INVALID_LEVEL 0xC0000148 +#define STATUS_WRONG_PASSWORD_CORE 0xC0000149 +#define STATUS_ILLEGAL_FLOAT_CONTEXT 0xC000014A +#define STATUS_PIPE_BROKEN 0xC000014B +#define STATUS_REGISTRY_CORRUPT 0xC000014C +#define STATUS_REGISTRY_IO_FAILED 0xC000014D +#define STATUS_NO_EVENT_PAIR 0xC000014E +#define STATUS_UNRECOGNIZED_VOLUME 0xC000014F +#define STATUS_SERIAL_NO_DEVICE_INITED 0xC0000150 +#define STATUS_NO_SUCH_ALIAS 0xC0000151 +#define STATUS_MEMBER_NOT_IN_ALIAS 0xC0000152 +#define STATUS_MEMBER_IN_ALIAS 0xC0000153 +#define STATUS_ALIAS_EXISTS 0xC0000154 +#define STATUS_LOGON_NOT_GRANTED 0xC0000155 +#define STATUS_TOO_MANY_SECRETS 0xC0000156 +#define STATUS_SECRET_TOO_LONG 0xC0000157 +#define STATUS_INTERNAL_DB_ERROR 0xC0000158 +#define STATUS_FULLSCREEN_MODE 0xC0000159 +#define STATUS_TOO_MANY_CONTEXT_IDS 0xC000015A +#define STATUS_LOGON_TYPE_NOT_GRANTED 0xC000015B +#define STATUS_NOT_REGISTRY_FILE 0xC000015C +#define STATUS_NT_CROSS_ENCRYPTION_REQUIRED 0xC000015D +#define STATUS_DOMAIN_CTRLR_CONFIG_ERROR 0xC000015E +#define STATUS_FT_MISSING_MEMBER 0xC000015F +#define STATUS_ILL_FORMED_SERVICE_ENTRY 0xC0000160 +#define STATUS_ILLEGAL_CHARACTER 0xC0000161 +#define STATUS_UNMAPPABLE_CHARACTER 0xC0000162 +#define STATUS_UNDEFINED_CHARACTER 0xC0000163 +#define STATUS_FLOPPY_VOLUME 0xC0000164 +#define STATUS_FLOPPY_ID_MARK_NOT_FOUND 0xC0000165 +#define STATUS_FLOPPY_WRONG_CYLINDER 0xC0000166 +#define STATUS_FLOPPY_UNKNOWN_ERROR 0xC0000167 +#define STATUS_FLOPPY_BAD_REGISTERS 0xC0000168 +#define STATUS_DISK_RECALIBRATE_FAILED 0xC0000169 +#define STATUS_DISK_OPERATION_FAILED 0xC000016A +#define STATUS_DISK_RESET_FAILED 0xC000016B +#define STATUS_SHARED_IRQ_BUSY 0xC000016C +#define STATUS_FT_ORPHANING 0xC000016D +#define STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT 0xC000016E + +#define STATUS_PARTITION_FAILURE 0xC0000172 +#define STATUS_INVALID_BLOCK_LENGTH 0xC0000173 +#define STATUS_DEVICE_NOT_PARTITIONED 0xC0000174 +#define STATUS_UNABLE_TO_LOCK_MEDIA 0xC0000175 +#define STATUS_UNABLE_TO_UNLOAD_MEDIA 0xC0000176 +#define STATUS_EOM_OVERFLOW 0xC0000177 +#define STATUS_NO_MEDIA 0xC0000178 +#define STATUS_NO_SUCH_MEMBER 0xC000017A +#define STATUS_INVALID_MEMBER 0xC000017B +#define STATUS_KEY_DELETED 0xC000017C +#define STATUS_NO_LOG_SPACE 0xC000017D +#define STATUS_TOO_MANY_SIDS 0xC000017E +#define STATUS_LM_CROSS_ENCRYPTION_REQUIRED 0xC000017F +#define STATUS_KEY_HAS_CHILDREN 0xC0000180 +#define STATUS_CHILD_MUST_BE_VOLATILE 0xC0000181 +#define STATUS_DEVICE_CONFIGURATION_ERROR 0xC0000182 +#define STATUS_DRIVER_INTERNAL_ERROR 0xC0000183 +#define STATUS_INVALID_DEVICE_STATE 0xC0000184 +#define STATUS_IO_DEVICE_ERROR 0xC0000185 +#define STATUS_DEVICE_PROTOCOL_ERROR 0xC0000186 +#define STATUS_BACKUP_CONTROLLER 0xC0000187 +#define STATUS_LOG_FILE_FULL 0xC0000188 +#define STATUS_TOO_LATE 0xC0000189 +#define STATUS_NO_TRUST_LSA_SECRET 0xC000018A +#define STATUS_NO_TRUST_SAM_ACCOUNT 0xC000018B +#define STATUS_TRUSTED_DOMAIN_FAILURE 0xC000018C +#define STATUS_TRUSTED_RELATIONSHIP_FAILURE 0xC000018D +#define STATUS_EVENTLOG_FILE_CORRUPT 0xC000018E +#define STATUS_EVENTLOG_CANT_START 0xC000018F +#define STATUS_TRUST_FAILURE 0xC0000190 +#define STATUS_MUTANT_LIMIT_EXCEEDED 0xC0000191 +#define STATUS_NETLOGON_NOT_STARTED 0xC0000192 +#define STATUS_ACCOUNT_EXPIRED 0xC0000193 +#define STATUS_POSSIBLE_DEADLOCK 0xC0000194 +#define STATUS_NETWORK_CREDENTIAL_CONFLICT 0xC0000195 +#define STATUS_REMOTE_SESSION_LIMIT 0xC0000196 +#define STATUS_EVENTLOG_FILE_CHANGED 0xC0000197 +#define STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT 0xC0000198 +#define STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT 0xC0000199 +#define STATUS_NOLOGON_SERVER_TRUST_ACCOUNT 0xC000019A +#define STATUS_DOMAIN_TRUST_INCONSISTENT 0xC000019B +#define STATUS_FS_DRIVER_REQUIRED 0xC000019C +#define STATUS_NO_USER_SESSION_KEY 0xC0000202 +#define STATUS_USER_SESSION_DELETED 0xC0000203 +#define STATUS_RESOURCE_LANG_NOT_FOUND 0xC0000204 +#define STATUS_INSUFF_SERVER_RESOURCES 0xC0000205 +#define STATUS_INVALID_BUFFER_SIZE 0xC0000206 +#define STATUS_INVALID_ADDRESS_COMPONENT 0xC0000207 +#define STATUS_INVALID_ADDRESS_WILDCARD 0xC0000208 +#define STATUS_TOO_MANY_ADDRESSES 0xC0000209 +#define STATUS_ADDRESS_ALREADY_EXISTS 0xC000020A +#define STATUS_ADDRESS_CLOSED 0xC000020B +#define STATUS_CONNECTION_DISCONNECTED 0xC000020C +#define STATUS_CONNECTION_RESET 0xC000020D +#define STATUS_TOO_MANY_NODES 0xC000020E +#define STATUS_TRANSACTION_ABORTED 0xC000020F +#define STATUS_TRANSACTION_TIMED_OUT 0xC0000210 +#define STATUS_TRANSACTION_NO_RELEASE 0xC0000211 +#define STATUS_TRANSACTION_NO_MATCH 0xC0000212 +#define STATUS_TRANSACTION_RESPONDED 0xC0000213 +#define STATUS_TRANSACTION_INVALID_ID 0xC0000214 +#define STATUS_TRANSACTION_INVALID_TYPE 0xC0000215 +#define STATUS_NOT_SERVER_SESSION 0xC0000216 +#define STATUS_NOT_CLIENT_SESSION 0xC0000217 +#define STATUS_CANNOT_LOAD_REGISTRY_FILE 0xC0000218 +#define STATUS_DEBUG_ATTACH_FAILED 0xC0000219 +#define STATUS_SYSTEM_PROCESS_TERMINATED 0xC000021A +#define STATUS_DATA_NOT_ACCEPTED 0xC000021B +#define STATUS_NO_BROWSER_SERVERS_FOUND 0xC000021C +#define STATUS_VDM_HARD_ERROR 0xC000021D +#define STATUS_DRIVER_CANCEL_TIMEOUT 0xC000021E +#define STATUS_REPLY_MESSAGE_MISMATCH 0xC000021F +#define STATUS_MAPPED_ALIGNMENT 0xC0000220 +#define STATUS_IMAGE_CHECKSUM_MISMATCH 0xC0000221 +#define STATUS_LOST_WRITEBEHIND_DATA 0xC0000222 +#define STATUS_CLIENT_SERVER_PARAMETERS_INVALID 0xC0000223 +#define STATUS_PASSWORD_MUST_CHANGE 0xC0000224 +#define STATUS_NOT_FOUND 0xC0000225 +#define STATUS_NOT_TINY_STREAM 0xC0000226 +#define STATUS_RECOVERY_FAILURE 0xC0000227 +#define STATUS_STACK_OVERFLOW_READ 0xC0000228 +#define STATUS_FAIL_CHECK 0xC0000229 +#define STATUS_DUPLICATE_OBJECTID 0xC000022A +#define STATUS_OBJECTID_EXISTS 0xC000022B +#define STATUS_CONVERT_TO_LARGE 0xC000022C +#define STATUS_RETRY 0xC000022D +#define STATUS_FOUND_OUT_OF_SCOPE 0xC000022E +#define STATUS_ALLOCATE_BUCKET 0xC000022F +#define STATUS_PROPSET_NOT_FOUND 0xC0000230 +#define STATUS_MARSHALL_OVERFLOW 0xC0000231 +#define STATUS_INVALID_VARIANT 0xC0000232 +#define STATUS_DOMAIN_CONTROLLER_NOT_FOUND 0xC0000233 +#define STATUS_ACCOUNT_LOCKED_OUT 0xC0000234 +#define STATUS_HANDLE_NOT_CLOSABLE 0xC0000235 +#define STATUS_CONNECTION_REFUSED 0xC0000236 +#define STATUS_GRACEFUL_DISCONNECT 0xC0000237 +#define STATUS_ADDRESS_ALREADY_ASSOCIATED 0xC0000238 +#define STATUS_ADDRESS_NOT_ASSOCIATED 0xC0000239 +#define STATUS_CONNECTION_INVALID 0xC000023A +#define STATUS_CONNECTION_ACTIVE 0xC000023B +#define STATUS_NETWORK_UNREACHABLE 0xC000023C +#define STATUS_HOST_UNREACHABLE 0xC000023D +#define STATUS_PROTOCOL_UNREACHABLE 0xC000023E +#define STATUS_PORT_UNREACHABLE 0xC000023F +#define STATUS_REQUEST_ABORTED 0xC0000240 +#define STATUS_CONNECTION_ABORTED 0xC0000241 +#define STATUS_BAD_COMPRESSION_BUFFER 0xC0000242 +#define STATUS_USER_MAPPED_FILE 0xC0000243 +#define STATUS_AUDIT_FAILED 0xC0000244 +#define STATUS_TIMER_RESOLUTION_NOT_SET 0xC0000245 +#define STATUS_CONNECTION_COUNT_LIMIT 0xC0000246 +#define STATUS_LOGIN_TIME_RESTRICTION 0xC0000247 +#define STATUS_LOGIN_WKSTA_RESTRICTION 0xC0000248 +#define STATUS_IMAGE_MP_UP_MISMATCH 0xC0000249 +#define STATUS_INSUFFICIENT_LOGON_INFO 0xC0000250 +#define STATUS_BAD_DLL_ENTRYPOINT 0xC0000251 +#define STATUS_BAD_SERVICE_ENTRYPOINT 0xC0000252 +#define STATUS_LPC_REPLY_LOST 0xC0000253 +#define STATUS_IP_ADDRESS_CONFLICT1 0xC0000254 +#define STATUS_IP_ADDRESS_CONFLICT2 0xC0000255 +#define STATUS_REGISTRY_QUOTA_LIMIT 0xC0000256 +#define STATUS_PATH_NOT_COVERED 0xC0000257 +#define STATUS_NO_CALLBACK_ACTIVE 0xC0000258 +#define STATUS_LICENSE_QUOTA_EXCEEDED 0xC0000259 +#define STATUS_PWD_TOO_SHORT 0xC000025A +#define STATUS_PWD_TOO_RECENT 0xC000025B +#define STATUS_PWD_HISTORY_CONFLICT 0xC000025C +#define STATUS_PLUGPLAY_NO_DEVICE 0xC000025E +#define STATUS_UNSUPPORTED_COMPRESSION 0xC000025F +#define STATUS_INVALID_HW_PROFILE 0xC0000260 +#define STATUS_INVALID_PLUGPLAY_DEVICE_PATH 0xC0000261 +#define STATUS_DRIVER_ORDINAL_NOT_FOUND 0xC0000262 +#define STATUS_DRIVER_ENTRYPOINT_NOT_FOUND 0xC0000263 +#define STATUS_RESOURCE_NOT_OWNED 0xC0000264 +#define STATUS_TOO_MANY_LINKS 0xC0000265 +#define STATUS_QUOTA_LIST_INCONSISTENT 0xC0000266 +#define STATUS_FILE_IS_OFFLINE 0xC0000267 +#define STATUS_EVALUATION_EXPIRATION 0xC0000268 +#define STATUS_ILLEGAL_DLL_RELOCATION 0xC0000269 +#define STATUS_LICENSE_VIOLATION 0xC000026A +#define STATUS_DLL_INIT_FAILED_LOGOFF 0xC000026B +#define STATUS_DRIVER_UNABLE_TO_LOAD 0xC000026C +#define STATUS_DFS_UNAVAILABLE 0xC000026D +#define STATUS_VOLUME_DISMOUNTED 0xC000026E +#define STATUS_WX86_INTERNAL_ERROR 0xC000026F +#define STATUS_WX86_FLOAT_STACK_CHECK 0xC0000270 +#define STATUS_VALIDATE_CONTINUE 0xC0000271 +#define STATUS_NO_MATCH 0xC0000272 +#define STATUS_NO_MORE_MATCHES 0xC0000273 +#define STATUS_NOT_A_REPARSE_POINT 0xC0000275 +#define STATUS_IO_REPARSE_TAG_INVALID 0xC0000276 +#define STATUS_IO_REPARSE_TAG_MISMATCH 0xC0000277 +#define STATUS_IO_REPARSE_DATA_INVALID 0xC0000278 +#define STATUS_IO_REPARSE_TAG_NOT_HANDLED 0xC0000279 +#define STATUS_REPARSE_POINT_NOT_RESOLVED 0xC0000280 +#define STATUS_DIRECTORY_IS_A_REPARSE_POINT 0xC0000281 +#define STATUS_RANGE_LIST_CONFLICT 0xC0000282 +#define STATUS_SOURCE_ELEMENT_EMPTY 0xC0000283 +#define STATUS_DESTINATION_ELEMENT_FULL 0xC0000284 +#define STATUS_ILLEGAL_ELEMENT_ADDRESS 0xC0000285 +#define STATUS_MAGAZINE_NOT_PRESENT 0xC0000286 +#define STATUS_REINITIALIZATION_NEEDED 0xC0000287 +#define STATUS_ENCRYPTION_FAILED 0xC000028A +#define STATUS_DECRYPTION_FAILED 0xC000028B +#define STATUS_RANGE_NOT_FOUND 0xC000028C +#define STATUS_NO_RECOVERY_POLICY 0xC000028D +#define STATUS_NO_EFS 0xC000028E +#define STATUS_WRONG_EFS 0xC000028F +#define STATUS_NO_USER_KEYS 0xC0000290 +#define STATUS_FILE_NOT_ENCRYPTED 0xC0000291 +#define STATUS_NOT_EXPORT_FORMAT 0xC0000292 +#define STATUS_FILE_ENCRYPTED 0xC0000293 +#define STATUS_WMI_GUID_NOT_FOUND 0xC0000295 +#define STATUS_WMI_INSTANCE_NOT_FOUND 0xC0000296 +#define STATUS_WMI_ITEMID_NOT_FOUND 0xC0000297 +#define STATUS_WMI_TRY_AGAIN 0xC0000298 +#define STATUS_SHARED_POLICY 0xC0000299 +#define STATUS_POLICY_OBJECT_NOT_FOUND 0xC000029A +#define STATUS_POLICY_ONLY_IN_DS 0xC000029B +#define STATUS_VOLUME_NOT_UPGRADED 0xC000029C +#define STATUS_REMOTE_STORAGE_NOT_ACTIVE 0xC000029D +#define STATUS_REMOTE_STORAGE_MEDIA_ERROR 0xC000029E +#define STATUS_NO_TRACKING_SERVICE 0xC000029F +#define STATUS_SERVER_SID_MISMATCH 0xC00002A0 +#define STATUS_DS_NO_ATTRIBUTE_OR_VALUE 0xC00002A1 +#define STATUS_DS_INVALID_ATTRIBUTE_SYNTAX 0xC00002A2 +#define STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED 0xC00002A3 +#define STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS 0xC00002A4 +#define STATUS_DS_BUSY 0xC00002A5 +#define STATUS_DS_UNAVAILABLE 0xC00002A6 +#define STATUS_DS_NO_RIDS_ALLOCATED 0xC00002A7 +#define STATUS_DS_NO_MORE_RIDS 0xC00002A8 +#define STATUS_DS_INCORRECT_ROLE_OWNER 0xC00002A9 +#define STATUS_DS_RIDMGR_INIT_ERROR 0xC00002AA +#define STATUS_DS_OBJ_CLASS_VIOLATION 0xC00002AB +#define STATUS_DS_CANT_ON_NON_LEAF 0xC00002AC +#define STATUS_DS_CANT_ON_RDN 0xC00002AD +#define STATUS_DS_CANT_MOD_OBJ_CLASS 0xC00002AE +#define STATUS_DS_CROSS_DOM_MOVE_FAILED 0xC00002AF +#define STATUS_DS_GC_NOT_AVAILABLE 0xC00002B0 +#define STATUS_DIRECTORY_SERVICE_REQUIRED 0xC00002B1 +#define STATUS_REPARSE_ATTRIBUTE_CONFLICT 0xC00002B2 +#define STATUS_CANT_ENABLE_DENY_ONLY 0xC00002B3 +#define STATUS_FLOAT_MULTIPLE_FAULTS 0xC00002B4 +#define STATUS_FLOAT_MULTIPLE_TRAPS 0xC00002B5 +#define STATUS_DEVICE_REMOVED 0xC00002B6 +#define STATUS_JOURNAL_DELETE_IN_PROGRESS 0xC00002B7 +#define STATUS_JOURNAL_NOT_ACTIVE 0xC00002B8 +#define STATUS_NOINTERFACE 0xC00002B9 +#define STATUS_DS_ADMIN_LIMIT_EXCEEDED 0xC00002C1 +#define STATUS_DRIVER_FAILED_SLEEP 0xC00002C2 +#define STATUS_MUTUAL_AUTHENTICATION_FAILED 0xC00002C3 +#define STATUS_CORRUPT_SYSTEM_FILE 0xC00002C4 +#define STATUS_DATATYPE_MISALIGNMENT_ERROR 0xC00002C5 +#define STATUS_WMI_READ_ONLY 0xC00002C6 +#define STATUS_WMI_SET_FAILURE 0xC00002C7 +#define STATUS_COMMITMENT_MINIMUM 0xC00002C8 +#define STATUS_REG_NAT_CONSUMPTION 0xC00002C9 +#define STATUS_TRANSPORT_FULL 0xC00002CA +#define STATUS_DS_SAM_INIT_FAILURE 0xC00002CB +#define STATUS_ONLY_IF_CONNECTED 0xC00002CC +#define STATUS_DS_SENSITIVE_GROUP_VIOLATION 0xC00002CD +#define STATUS_PNP_RESTART_ENUMERATION 0xC00002CE +#define STATUS_JOURNAL_ENTRY_DELETED 0xC00002CF +#define STATUS_DS_CANT_MOD_PRIMARYGROUPID 0xC00002D0 +#define STATUS_SYSTEM_IMAGE_BAD_SIGNATURE 0xC00002D1 +#define STATUS_PNP_REBOOT_REQUIRED 0xC00002D2 +#define STATUS_POWER_STATE_INVALID 0xC00002D3 +#define STATUS_DS_INVALID_GROUP_TYPE 0xC00002D4 +#define STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN 0xC00002D5 +#define STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN 0xC00002D6 +#define STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER 0xC00002D7 +#define STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER 0xC00002D8 +#define STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER 0xC00002D9 +#define STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER 0xC00002DA +#define STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER 0xC00002DB +#define STATUS_DS_HAVE_PRIMARY_MEMBERS 0xC00002DC +#define STATUS_WMI_NOT_SUPPORTED 0xC00002DD +#define STATUS_INSUFFICIENT_POWER 0xC00002DE +#define STATUS_SAM_NEED_BOOTKEY_PASSWORD 0xC00002DF +#define STATUS_SAM_NEED_BOOTKEY_FLOPPY 0xC00002E0 +#define STATUS_DS_CANT_START 0xC00002E1 +#define STATUS_DS_INIT_FAILURE 0xC00002E2 +#define STATUS_SAM_INIT_FAILURE 0xC00002E3 +#define STATUS_DS_GC_REQUIRED 0xC00002E4 +#define STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY 0xC00002E5 +#define STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS 0xC00002E6 +#define STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED 0xC00002E7 +#define STATUS_MULTIPLE_FAULT_VIOLATION 0xC00002E8 +#define STATUS_CURRENT_DOMAIN_NOT_ALLOWED 0xC00002E9 +#define STATUS_CANNOT_MAKE 0xC00002EA +#define STATUS_SYSTEM_SHUTDOWN 0xC00002EB +#define STATUS_DS_INIT_FAILURE_CONSOLE 0xC00002EC +#define STATUS_DS_SAM_INIT_FAILURE_CONSOLE 0xC00002ED +#define STATUS_UNFINISHED_CONTEXT_DELETED 0xC00002EE +#define STATUS_NO_TGT_REPLY 0xC00002EF +#define STATUS_OBJECTID_NOT_FOUND 0xC00002F0 +#define STATUS_NO_IP_ADDRESSES 0xC00002F1 +#define STATUS_WRONG_CREDENTIAL_HANDLE 0xC00002F2 +#define STATUS_CRYPTO_SYSTEM_INVALID 0xC00002F3 +#define STATUS_MAX_REFERRALS_EXCEEDED 0xC00002F4 +#define STATUS_MUST_BE_KDC 0xC00002F5 +#define STATUS_STRONG_CRYPTO_NOT_SUPPORTED 0xC00002F6 +#define STATUS_TOO_MANY_PRINCIPALS 0xC00002F7 +#define STATUS_NO_PA_DATA 0xC00002F8 +#define STATUS_PKINIT_NAME_MISMATCH 0xC00002F9 +#define STATUS_SMARTCARD_LOGON_REQUIRED 0xC00002FA +#define STATUS_KDC_INVALID_REQUEST 0xC00002FB +#define STATUS_KDC_UNABLE_TO_REFER 0xC00002FC +#define STATUS_KDC_UNKNOWN_ETYPE 0xC00002FD +#define STATUS_SHUTDOWN_IN_PROGRESS 0xC00002FE +#define STATUS_SERVER_SHUTDOWN_IN_PROGRESS 0xC00002FF +#define STATUS_NOT_SUPPORTED_ON_SBS 0xC0000300 +#define STATUS_WMI_GUID_DISCONNECTED 0xC0000301 +#define STATUS_WMI_ALREADY_DISABLED 0xC0000302 +#define STATUS_WMI_ALREADY_ENABLED 0xC0000303 +#define STATUS_MFT_TOO_FRAGMENTED 0xC0000304 +#define STATUS_COPY_PROTECTION_FAILURE 0xC0000305 +#define STATUS_CSS_AUTHENTICATION_FAILURE 0xC0000306 +#define STATUS_CSS_KEY_NOT_PRESENT 0xC0000307 +#define STATUS_CSS_KEY_NOT_ESTABLISHED 0xC0000308 +#define STATUS_CSS_SCRAMBLED_SECTOR 0xC0000309 +#define STATUS_CSS_REGION_MISMATCH 0xC000030A +#define STATUS_CSS_RESETS_EXHAUSTED 0xC000030B +#define STATUS_PKINIT_FAILURE 0xC0000320 +#define STATUS_SMARTCARD_SUBSYSTEM_FAILURE 0xC0000321 +#define STATUS_NO_KERB_KEY 0xC0000322 +#define STATUS_HOST_DOWN 0xC0000350 +#define STATUS_UNSUPPORTED_PREAUTH 0xC0000351 +#define STATUS_EFS_ALG_BLOB_TOO_BIG 0xC0000352 +#define STATUS_PORT_NOT_SET 0xC0000353 +#define STATUS_DEBUGGER_INACTIVE 0xC0000354 +#define STATUS_DS_VERSION_CHECK_FAILURE 0xC0000355 +#define STATUS_AUDITING_DISABLED 0xC0000356 +#define STATUS_PRENT4_MACHINE_ACCOUNT 0xC0000357 +#define STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER 0xC0000358 +#define STATUS_INVALID_IMAGE_WIN_32 0xC0000359 +#define STATUS_INVALID_IMAGE_WIN_64 0xC000035A +#define STATUS_BAD_BINDINGS 0xC000035B +#define STATUS_NETWORK_SESSION_EXPIRED 0xC000035C +#define STATUS_APPHELP_BLOCK 0xC000035D +#define STATUS_ALL_SIDS_FILTERED 0xC000035E +#define STATUS_NOT_SAFE_MODE_DRIVER 0xC000035F +#define STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT 0xC0000361 +#define STATUS_ACCESS_DISABLED_BY_POLICY_PATH 0xC0000362 +#define STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER 0xC0000363 +#define STATUS_ACCESS_DISABLED_BY_POLICY_OTHER 0xC0000364 +#define STATUS_FAILED_DRIVER_ENTRY 0xC0000365 +#define STATUS_DEVICE_ENUMERATION_ERROR 0xC0000366 +#define STATUS_WAIT_FOR_OPLOCK 0xC0000367 +#define STATUS_MOUNT_POINT_NOT_RESOLVED 0xC0000368 +#define STATUS_INVALID_DEVICE_OBJECT_PARAMETER 0xC0000369 +#define STATUS_MCA_OCCURED 0xC000036A +#define STATUS_DRIVER_BLOCKED_CRITICAL 0xC000036B +#define STATUS_DRIVER_BLOCKED 0xC000036C +#define STATUS_DRIVER_DATABASE_ERROR 0xC000036D +#define STATUS_SYSTEM_HIVE_TOO_LARGE 0xC000036E +#define STATUS_INVALID_IMPORT_OF_NON_DLL 0xC000036F +#define STATUS_SMARTCARD_WRONG_PIN 0xC0000380 +#define STATUS_SMARTCARD_CARD_BLOCKED 0xC0000381 +#define STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED 0xC0000382 +#define STATUS_SMARTCARD_NO_CARD 0xC0000383 +#define STATUS_SMARTCARD_NO_KEY_CONTAINER 0xC0000384 +#define STATUS_SMARTCARD_NO_CERTIFICATE 0xC0000385 +#define STATUS_SMARTCARD_NO_KEYSET 0xC0000386 +#define STATUS_SMARTCARD_IO_ERROR 0xC0000387 +#define STATUS_DOWNGRADE_DETECTED 0xC0000388 +#define STATUS_SMARTCARD_CERT_REVOKED 0xC0000389 +#define STATUS_ISSUING_CA_UNTRUSTED 0xC000038A +#define STATUS_REVOCATION_OFFLINE_C 0xC000038B +#define STATUS_PKINIT_CLIENT_FAILURE 0xC000038C +#define STATUS_SMARTCARD_CERT_EXPIRED 0xC000038D +#define STATUS_DRIVER_FAILED_PRIOR_UNLOAD 0xC000038E +#define STATUS_SMARTCARD_SILENT_CONTEXT 0xC000038F +#define STATUS_PER_USER_TRUST_QUOTA_EXCEEDED 0xC0000401 +#define STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED 0xC0000402 +#define STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED 0xC0000403 +#define STATUS_DS_NAME_NOT_UNIQUE 0xC0000404 +#define STATUS_DS_DUPLICATE_ID_FOUND 0xC0000405 +#define STATUS_DS_GROUP_CONVERSION_ERROR 0xC0000406 +#define STATUS_VOLSNAP_PREPARE_HIBERNATE 0xC0000407 +#define STATUS_USER2USER_REQUIRED 0xC0000408 +#define STATUS_STACK_BUFFER_OVERRUN 0xC0000409 +#define STATUS_NO_S4U_PROT_SUPPORT 0xC000040A +#define STATUS_CROSSREALM_DELEGATION_FAILURE 0xC000040B +#define STATUS_REVOCATION_OFFLINE_KDC 0xC000040C +#define STATUS_ISSUING_CA_UNTRUSTED_KDC 0xC000040D +#define STATUS_KDC_CERT_EXPIRED 0xC000040E +#define STATUS_KDC_CERT_REVOKED 0xC000040F +#define STATUS_PARAMETER_QUOTA_EXCEEDED 0xC0000410 +#define STATUS_HIBERNATION_FAILURE 0xC0000411 +#define STATUS_DELAY_LOAD_FAILED 0xC0000412 +#define STATUS_AUTHENTICATION_FIREWALL_FAILED 0xC0000413 +#define STATUS_VDM_DISALLOWED 0xC0000414 +#define STATUS_HUNG_DISPLAY_DRIVER_THREAD 0xC0000415 +#define STATUS_WOW_ASSERTION 0xC0009898 + +#define RPC_NT_INVALID_STRING_BINDING 0xC0020001 +#define RPC_NT_WRONG_KIND_OF_BINDING 0xC0020002 +#define RPC_NT_INVALID_BINDING 0xC0020003 +#define RPC_NT_PROTSEQ_NOT_SUPPORTED 0xC0020004 +#define RPC_NT_INVALID_RPC_PROTSEQ 0xC0020005 +#define RPC_NT_INVALID_STRING_UUID 0xC0020006 +#define RPC_NT_INVALID_ENDPOINT_FORMAT 0xC0020007 +#define RPC_NT_INVALID_NET_ADDR 0xC0020008 +#define RPC_NT_NO_ENDPOINT_FOUND 0xC0020009 +#define RPC_NT_INVALID_TIMEOUT 0xC002000A +#define RPC_NT_OBJECT_NOT_FOUND 0xC002000B +#define RPC_NT_ALREADY_REGISTERED 0xC002000C +#define RPC_NT_TYPE_ALREADY_REGISTERED 0xC002000D +#define RPC_NT_ALREADY_LISTENING 0xC002000E +#define RPC_NT_NO_PROTSEQS_REGISTERED 0xC002000F +#define RPC_NT_NOT_LISTENING 0xC0020010 +#define RPC_NT_UNKNOWN_MGR_TYPE 0xC0020011 +#define RPC_NT_UNKNOWN_IF 0xC0020012 +#define RPC_NT_NO_BINDINGS 0xC0020013 +#define RPC_NT_NO_PROTSEQS 0xC0020014 +#define RPC_NT_CANT_CREATE_ENDPOINT 0xC0020015 +#define RPC_NT_OUT_OF_RESOURCES 0xC0020016 +#define RPC_NT_SERVER_UNAVAILABLE 0xC0020017 +#define RPC_NT_SERVER_TOO_BUSY 0xC0020018 +#define RPC_NT_INVALID_NETWORK_OPTIONS 0xC0020019 +#define RPC_NT_NO_CALL_ACTIVE 0xC002001A +#define RPC_NT_CALL_FAILED 0xC002001B +#define RPC_NT_CALL_FAILED_DNE 0xC002001C +#define RPC_NT_PROTOCOL_ERROR 0xC002001D +#define RPC_NT_UNSUPPORTED_TRANS_SYN 0xC002001F +#define RPC_NT_UNSUPPORTED_TYPE 0xC0020021 +#define RPC_NT_INVALID_TAG 0xC0020022 +#define RPC_NT_INVALID_BOUND 0xC0020023 +#define RPC_NT_NO_ENTRY_NAME 0xC0020024 +#define RPC_NT_INVALID_NAME_SYNTAX 0xC0020025 +#define RPC_NT_UNSUPPORTED_NAME_SYNTAX 0xC0020026 +#define RPC_NT_UUID_NO_ADDRESS 0xC0020028 +#define RPC_NT_DUPLICATE_ENDPOINT 0xC0020029 +#define RPC_NT_UNKNOWN_AUTHN_TYPE 0xC002002A +#define RPC_NT_MAX_CALLS_TOO_SMALL 0xC002002B +#define RPC_NT_STRING_TOO_LONG 0xC002002C +#define RPC_NT_PROTSEQ_NOT_FOUND 0xC002002D +#define RPC_NT_PROCNUM_OUT_OF_RANGE 0xC002002E +#define RPC_NT_BINDING_HAS_NO_AUTH 0xC002002F +#define RPC_NT_UNKNOWN_AUTHN_SERVICE 0xC0020030 +#define RPC_NT_UNKNOWN_AUTHN_LEVEL 0xC0020031 +#define RPC_NT_INVALID_AUTH_IDENTITY 0xC0020032 +#define RPC_NT_UNKNOWN_AUTHZ_SERVICE 0xC0020033 +#define EPT_NT_INVALID_ENTRY 0xC0020034 +#define EPT_NT_CANT_PERFORM_OP 0xC0020035 +#define EPT_NT_NOT_REGISTERED 0xC0020036 +#define RPC_NT_NOTHING_TO_EXPORT 0xC0020037 +#define RPC_NT_INCOMPLETE_NAME 0xC0020038 +#define RPC_NT_INVALID_VERS_OPTION 0xC0020039 +#define RPC_NT_NO_MORE_MEMBERS 0xC002003A +#define RPC_NT_NOT_ALL_OBJS_UNEXPORTED 0xC002003B +#define RPC_NT_INTERFACE_NOT_FOUND 0xC002003C +#define RPC_NT_ENTRY_ALREADY_EXISTS 0xC002003D +#define RPC_NT_ENTRY_NOT_FOUND 0xC002003E +#define RPC_NT_NAME_SERVICE_UNAVAILABLE 0xC002003F +#define RPC_NT_INVALID_NAF_ID 0xC0020040 +#define RPC_NT_CANNOT_SUPPORT 0xC0020041 +#define RPC_NT_NO_CONTEXT_AVAILABLE 0xC0020042 +#define RPC_NT_INTERNAL_ERROR 0xC0020043 +#define RPC_NT_ZERO_DIVIDE 0xC0020044 +#define RPC_NT_ADDRESS_ERROR 0xC0020045 +#define RPC_NT_FP_DIV_ZERO 0xC0020046 +#define RPC_NT_FP_UNDERFLOW 0xC0020047 +#define RPC_NT_FP_OVERFLOW 0xC0020048 +#define RPC_NT_CALL_IN_PROGRESS 0xC0020049 +#define RPC_NT_NO_MORE_BINDINGS 0xC002004A +#define RPC_NT_GROUP_MEMBER_NOT_FOUND 0xC002004B +#define EPT_NT_CANT_CREATE 0xC002004C +#define RPC_NT_INVALID_OBJECT 0xC002004D +#define RPC_NT_NO_INTERFACES 0xC002004F +#define RPC_NT_CALL_CANCELLED 0xC0020050 +#define RPC_NT_BINDING_INCOMPLETE 0xC0020051 +#define RPC_NT_COMM_FAILURE 0xC0020052 +#define RPC_NT_UNSUPPORTED_AUTHN_LEVEL 0xC0020053 +#define RPC_NT_NO_PRINC_NAME 0xC0020054 +#define RPC_NT_NOT_RPC_ERROR 0xC0020055 +#define RPC_NT_SEC_PKG_ERROR 0xC0020057 +#define RPC_NT_NOT_CANCELLED 0xC0020058 +#define RPC_NT_INVALID_ASYNC_HANDLE 0xC0020062 +#define RPC_NT_INVALID_ASYNC_CALL 0xC0020063 + +#define RPC_NT_NO_MORE_ENTRIES 0xC0030001 +#define RPC_NT_SS_CHAR_TRANS_OPEN_FAIL 0xC0030002 +#define RPC_NT_SS_CHAR_TRANS_SHORT_FILE 0xC0030003 +#define RPC_NT_SS_IN_NULL_CONTEXT 0xC0030004 +#define RPC_NT_SS_CONTEXT_MISMATCH 0xC0030005 +#define RPC_NT_SS_CONTEXT_DAMAGED 0xC0030006 +#define RPC_NT_SS_HANDLES_MISMATCH 0xC0030007 +#define RPC_NT_SS_CANNOT_GET_CALL_HANDLE 0xC0030008 +#define RPC_NT_NULL_REF_POINTER 0xC0030009 +#define RPC_NT_ENUM_VALUE_OUT_OF_RANGE 0xC003000A +#define RPC_NT_BYTE_COUNT_TOO_SMALL 0xC003000B +#define RPC_NT_BAD_STUB_DATA 0xC003000C +#define RPC_NT_INVALID_ES_ACTION 0xC0030059 +#define RPC_NT_WRONG_ES_VERSION 0xC003005A +#define RPC_NT_WRONG_STUB_VERSION 0xC003005B +#define RPC_NT_INVALID_PIPE_OBJECT 0xC003005C +#define RPC_NT_INVALID_PIPE_OPERATION 0xC003005D +#define RPC_NT_WRONG_PIPE_VERSION 0xC003005E +#define RPC_NT_PIPE_CLOSED 0xC003005F +#define RPC_NT_PIPE_DISCIPLINE_ERROR 0xC0030060 +#define RPC_NT_PIPE_EMPTY 0xC0030061 + +#define STATUS_PNP_BAD_MPS_TABLE 0xC0040035 +#define STATUS_PNP_TRANSLATION_FAILED 0xC0040036 +#define STATUS_PNP_IRQ_TRANSLATION_FAILED 0xC0040037 +#define STATUS_PNP_INVALID_ID 0xC0040038 + +#define STATUS_CTX_WINSTATION_NAME_INVALID 0xC00A0001 +#define STATUS_CTX_INVALID_PD 0xC00A0002 +#define STATUS_CTX_PD_NOT_FOUND 0xC00A0003 +#define STATUS_CTX_CLOSE_PENDING 0xC00A0006 +#define STATUS_CTX_NO_OUTBUF 0xC00A0007 +#define STATUS_CTX_MODEM_INF_NOT_FOUND 0xC00A0008 +#define STATUS_CTX_INVALID_MODEMNAME 0xC00A0009 +#define STATUS_CTX_RESPONSE_ERROR 0xC00A000A +#define STATUS_CTX_MODEM_RESPONSE_TIMEOUT 0xC00A000B +#define STATUS_CTX_MODEM_RESPONSE_NO_CARRIER 0xC00A000C +#define STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE 0xC00A000D +#define STATUS_CTX_MODEM_RESPONSE_BUSY 0xC00A000E +#define STATUS_CTX_MODEM_RESPONSE_VOICE 0xC00A000F +#define STATUS_CTX_TD_ERROR 0xC00A0010 +#define STATUS_CTX_LICENSE_CLIENT_INVALID 0xC00A0012 +#define STATUS_CTX_LICENSE_NOT_AVAILABLE 0xC00A0013 +#define STATUS_CTX_LICENSE_EXPIRED 0xC00A0014 +#define STATUS_CTX_WINSTATION_NOT_FOUND 0xC00A0015 +#define STATUS_CTX_WINSTATION_NAME_COLLISION 0xC00A0016 +#define STATUS_CTX_WINSTATION_BUSY 0xC00A0017 +#define STATUS_CTX_BAD_VIDEO_MODE 0xC00A0018 +#define STATUS_CTX_GRAPHICS_INVALID 0xC00A0022 +#define STATUS_CTX_NOT_CONSOLE 0xC00A0024 +#define STATUS_CTX_CLIENT_QUERY_TIMEOUT 0xC00A0026 +#define STATUS_CTX_CONSOLE_DISCONNECT 0xC00A0027 +#define STATUS_CTX_CONSOLE_CONNECT 0xC00A0028 +#define STATUS_CTX_SHADOW_DENIED 0xC00A002A +#define STATUS_CTX_WINSTATION_ACCESS_DENIED 0xC00A002B +#define STATUS_CTX_INVALID_WD 0xC00A002E +#define STATUS_CTX_WD_NOT_FOUND 0xC00A002F +#define STATUS_CTX_SHADOW_INVALID 0xC00A0030 +#define STATUS_CTX_SHADOW_DISABLED 0xC00A0031 +#define STATUS_RDP_PROTOCOL_ERROR 0xC00A0032 +#define STATUS_CTX_CLIENT_LICENSE_NOT_SET 0xC00A0033 +#define STATUS_CTX_CLIENT_LICENSE_IN_USE 0xC00A0034 +#define STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE 0xC00A0035 +#define STATUS_CTX_SHADOW_NOT_RUNNING 0xC00A0036 + +#define STATUS_CLUSTER_INVALID_NODE 0xC0130001 +#define STATUS_CLUSTER_NODE_EXISTS 0xC0130002 +#define STATUS_CLUSTER_JOIN_IN_PROGRESS 0xC0130003 +#define STATUS_CLUSTER_NODE_NOT_FOUND 0xC0130004 +#define STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND 0xC0130005 +#define STATUS_CLUSTER_NETWORK_EXISTS 0xC0130006 +#define STATUS_CLUSTER_NETWORK_NOT_FOUND 0xC0130007 +#define STATUS_CLUSTER_NETINTERFACE_EXISTS 0xC0130008 +#define STATUS_CLUSTER_NETINTERFACE_NOT_FOUND 0xC0130009 +#define STATUS_CLUSTER_INVALID_REQUEST 0xC013000A +#define STATUS_CLUSTER_INVALID_NETWORK_PROVIDER 0xC013000B +#define STATUS_CLUSTER_NODE_DOWN 0xC013000C +#define STATUS_CLUSTER_NODE_UNREACHABLE 0xC013000D +#define STATUS_CLUSTER_NODE_NOT_MEMBER 0xC013000E +#define STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS 0xC013000F +#define STATUS_CLUSTER_INVALID_NETWORK 0xC0130010 +#define STATUS_CLUSTER_NO_NET_ADAPTERS 0xC0130011 +#define STATUS_CLUSTER_NODE_UP 0xC0130012 +#define STATUS_CLUSTER_NODE_PAUSED 0xC0130013 +#define STATUS_CLUSTER_NODE_NOT_PAUSED 0xC0130014 +#define STATUS_CLUSTER_NO_SECURITY_CONTEXT 0xC0130015 +#define STATUS_CLUSTER_NETWORK_NOT_INTERNAL 0xC0130016 +#define STATUS_CLUSTER_POISONED 0xC0130017 + +#define STATUS_SXS_SECTION_NOT_FOUND 0xC0150001 +#define STATUS_SXS_CANT_GEN_ACTCTX 0xC0150002 +#define STATUS_SXS_INVALID_ACTCTXDATA_FORMAT 0xC0150003 +#define STATUS_SXS_ASSEMBLY_NOT_FOUND 0xC0150004 +#define STATUS_SXS_MANIFEST_FORMAT_ERROR 0xC0150005 +#define STATUS_SXS_MANIFEST_PARSE_ERROR 0xC0150006 +#define STATUS_SXS_ACTIVATION_CONTEXT_DISABLED 0xC0150007 +#define STATUS_SXS_KEY_NOT_FOUND 0xC0150008 +#define STATUS_SXS_VERSION_CONFLICT 0xC0150009 +#define STATUS_SXS_WRONG_SECTION_TYPE 0xC015000A +#define STATUS_SXS_THREAD_QUERIES_DISABLED 0xC015000B +#define STATUS_SXS_ASSEMBLY_MISSING 0xC015000C +#define STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET 0xC015000E +#define STATUS_SXS_EARLY_DEACTIVATION 0xC015000F +#define STATUS_SXS_INVALID_DEACTIVATION 0xC0150010 +#define STATUS_SXS_MULTIPLE_DEACTIVATION 0xC0150011 +#define STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY 0xC0150012 +#define STATUS_SXS_PROCESS_TERMINATION_REQUESTED 0xC0150013 +#define STATUS_SXS_CORRUPT_ACTIVATION_STACK 0xC0150014 +#define STATUS_SXS_CORRUPTION 0xC0150015 + +#endif /* WIN32_NO_STATUS */ + +#ifndef __VALUE_STRING_H__ +#define __VALUE_STRING_H__ + +typedef struct _value_string { + uint32_t value; + const char * strptr; +} value_string; + +/* + * NT error codes. + * + * From + * + * http://www.wildpackets.com/elements/SMB_NT_Status_Codes.txt + */ +static const value_string NT_errors[] = { + { 0x00000000, "STATUS_SUCCESS" }, + { 0x00000000, "STATUS_WAIT_0" }, + { 0x00000001, "STATUS_WAIT_1" }, + { 0x00000002, "STATUS_WAIT_2" }, + { 0x00000003, "STATUS_WAIT_3" }, + { 0x0000003F, "STATUS_WAIT_63" }, + { 0x00000080, "STATUS_ABANDONED" }, + { 0x00000080, "STATUS_ABANDONED_WAIT_0" }, + { 0x000000BF, "STATUS_ABANDONED_WAIT_63" }, + { 0x000000C0, "STATUS_USER_APC" }, + { 0x00000100, "STATUS_KERNEL_APC" }, + { 0x00000101, "STATUS_ALERTED" }, + { 0x00000102, "STATUS_TIMEOUT" }, + { 0x00000103, "STATUS_PENDING" }, + { 0x00000104, "STATUS_REPARSE" }, + { 0x00000105, "STATUS_MORE_ENTRIES" }, + { 0x00000106, "STATUS_NOT_ALL_ASSIGNED" }, + { 0x00000107, "STATUS_SOME_NOT_MAPPED" }, + { 0x00000108, "STATUS_OPLOCK_BREAK_IN_PROGRESS" }, + { 0x00000109, "STATUS_VOLUME_MOUNTED" }, + { 0x0000010A, "STATUS_RXACT_COMMITTED" }, + { 0x0000010B, "STATUS_NOTIFY_CLEANUP" }, + { 0x0000010C, "STATUS_NOTIFY_ENUM_DIR" }, + { 0x0000010D, "STATUS_NO_QUOTAS_FOR_ACCOUNT" }, + { 0x0000010E, "STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED" }, + { 0x00000110, "STATUS_PAGE_FAULT_TRANSITION" }, + { 0x00000111, "STATUS_PAGE_FAULT_DEMAND_ZERO" }, + { 0x00000112, "STATUS_PAGE_FAULT_COPY_ON_WRITE" }, + { 0x00000113, "STATUS_PAGE_FAULT_GUARD_PAGE" }, + { 0x00000114, "STATUS_PAGE_FAULT_PAGING_FILE" }, + { 0x00000115, "STATUS_CACHE_PAGE_LOCKED" }, + { 0x00000116, "STATUS_CRASH_DUMP" }, + { 0x00000117, "STATUS_BUFFER_ALL_ZEROS" }, + { 0x00000118, "STATUS_REPARSE_OBJECT" }, + { 0x0000045C, "STATUS_NO_SHUTDOWN_IN_PROGRESS" }, + { 0x40000000, "STATUS_OBJECT_NAME_EXISTS" }, + { 0x40000001, "STATUS_THREAD_WAS_SUSPENDED" }, + { 0x40000002, "STATUS_WORKING_SET_LIMIT_RANGE" }, + { 0x40000003, "STATUS_IMAGE_NOT_AT_BASE" }, + { 0x40000004, "STATUS_RXACT_STATE_CREATED" }, + { 0x40000005, "STATUS_SEGMENT_NOTIFICATION" }, + { 0x40000006, "STATUS_LOCAL_USER_SESSION_KEY" }, + { 0x40000007, "STATUS_BAD_CURRENT_DIRECTORY" }, + { 0x40000008, "STATUS_SERIAL_MORE_WRITES" }, + { 0x40000009, "STATUS_REGISTRY_RECOVERED" }, + { 0x4000000A, "STATUS_FT_READ_RECOVERY_FROM_BACKUP" }, + { 0x4000000B, "STATUS_FT_WRITE_RECOVERY" }, + { 0x4000000C, "STATUS_SERIAL_COUNTER_TIMEOUT" }, + { 0x4000000D, "STATUS_NULL_LM_PASSWORD" }, + { 0x4000000E, "STATUS_IMAGE_MACHINE_TYPE_MISMATCH" }, + { 0x4000000F, "STATUS_RECEIVE_PARTIAL" }, + { 0x40000010, "STATUS_RECEIVE_EXPEDITED" }, + { 0x40000011, "STATUS_RECEIVE_PARTIAL_EXPEDITED" }, + { 0x40000012, "STATUS_EVENT_DONE" }, + { 0x40000013, "STATUS_EVENT_PENDING" }, + { 0x40000014, "STATUS_CHECKING_FILE_SYSTEM" }, + { 0x40000015, "STATUS_FATAL_APP_EXIT" }, + { 0x40000016, "STATUS_PREDEFINED_HANDLE" }, + { 0x40000017, "STATUS_WAS_UNLOCKED" }, + { 0x40000018, "STATUS_SERVICE_NOTIFICATION" }, + { 0x40000019, "STATUS_WAS_LOCKED" }, + { 0x4000001A, "STATUS_LOG_HARD_ERROR" }, + { 0x4000001B, "STATUS_ALREADY_WIN32" }, + { 0x4000001C, "STATUS_WX86_UNSIMULATE" }, + { 0x4000001D, "STATUS_WX86_CONTINUE" }, + { 0x4000001E, "STATUS_WX86_SINGLE_STEP" }, + { 0x4000001F, "STATUS_WX86_BREAKPOINT" }, + { 0x40000020, "STATUS_WX86_EXCEPTION_CONTINUE" }, + { 0x40000021, "STATUS_WX86_EXCEPTION_LASTCHANCE" }, + { 0x40000022, "STATUS_WX86_EXCEPTION_CHAIN" }, + { 0x40000023, "STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE" }, + { 0x40000024, "STATUS_NO_YIELD_PERFORMED" }, + { 0x40000025, "STATUS_TIMER_RESUME_IGNORED" }, + { 0x80000001, "STATUS_GUARD_PAGE_VIOLATION" }, + { 0x80000002, "STATUS_DATATYPE_MISALIGNMENT" }, + { 0x80000003, "STATUS_BREAKPOINT" }, + { 0x80000004, "STATUS_SINGLE_STEP" }, + { 0x80000005, "STATUS_BUFFER_OVERFLOW" }, + { 0x80000006, "STATUS_NO_MORE_FILES" }, + { 0x80000007, "STATUS_WAKE_SYSTEM_DEBUGGER" }, + { 0x8000000A, "STATUS_HANDLES_CLOSED" }, + { 0x8000000B, "STATUS_NO_INHERITANCE" }, + { 0x8000000C, "STATUS_GUID_SUBSTITUTION_MADE" }, + { 0x8000000D, "STATUS_PARTIAL_COPY" }, + { 0x8000000E, "STATUS_DEVICE_PAPER_EMPTY" }, + { 0x8000000F, "STATUS_DEVICE_POWERED_OFF" }, + { 0x80000010, "STATUS_DEVICE_OFF_LINE" }, + { 0x80000011, "STATUS_DEVICE_BUSY" }, + { 0x80000012, "STATUS_NO_MORE_EAS" }, + { 0x80000013, "STATUS_INVALID_EA_NAME" }, + { 0x80000014, "STATUS_EA_LIST_INCONSISTENT" }, + { 0x80000015, "STATUS_INVALID_EA_FLAG" }, + { 0x80000016, "STATUS_VERIFY_REQUIRED" }, + { 0x80000017, "STATUS_EXTRANEOUS_INFORMATION" }, + { 0x80000018, "STATUS_RXACT_COMMIT_NECESSARY" }, + { 0x8000001A, "STATUS_NO_MORE_ENTRIES" }, + { 0x8000001B, "STATUS_FILEMARK_DETECTED" }, + { 0x8000001C, "STATUS_MEDIA_CHANGED" }, + { 0x8000001D, "STATUS_BUS_RESET" }, + { 0x8000001E, "STATUS_END_OF_MEDIA" }, + { 0x8000001F, "STATUS_BEGINNING_OF_MEDIA" }, + { 0x80000020, "STATUS_MEDIA_CHECK" }, + { 0x80000021, "STATUS_SETMARK_DETECTED" }, + { 0x80000022, "STATUS_NO_DATA_DETECTED" }, + { 0x80000023, "STATUS_REDIRECTOR_HAS_OPEN_HANDLES" }, + { 0x80000024, "STATUS_SERVER_HAS_OPEN_HANDLES" }, + { 0x80000025, "STATUS_ALREADY_DISCONNECTED" }, + { 0x80000026, "STATUS_LONGJUMP" }, + { 0x80040111, "MAPI_E_LOGON_FAILED" }, + { 0x80090300, "SEC_E_INSUFFICIENT_MEMORY" }, + { 0x80090301, "SEC_E_INVALID_HANDLE" }, + { 0x80090302, "SEC_E_UNSUPPORTED_FUNCTION" }, + { 0x8009030B, "SEC_E_NO_IMPERSONATION" }, + { 0x8009030D, "SEC_E_UNKNOWN_CREDENTIALS" }, + { 0x8009030E, "SEC_E_NO_CREDENTIALS" }, + { 0x8009030F, "SEC_E_MESSAGE_ALTERED" }, + { 0x80090310, "SEC_E_OUT_OF_SEQUENCE" }, + { 0x80090311, "SEC_E_NO_AUTHENTICATING_AUTHORITY" }, + { 0xC0000001, "STATUS_UNSUCCESSFUL" }, + { 0xC0000002, "STATUS_NOT_IMPLEMENTED" }, + { 0xC0000003, "STATUS_INVALID_INFO_CLASS" }, + { 0xC0000004, "STATUS_INFO_LENGTH_MISMATCH" }, + { 0xC0000005, "STATUS_ACCESS_VIOLATION" }, + { 0xC0000006, "STATUS_IN_PAGE_ERROR" }, + { 0xC0000007, "STATUS_PAGEFILE_QUOTA" }, + { 0xC0000008, "STATUS_INVALID_HANDLE" }, + { 0xC0000009, "STATUS_BAD_INITIAL_STACK" }, + { 0xC000000A, "STATUS_BAD_INITIAL_PC" }, + { 0xC000000B, "STATUS_INVALID_CID" }, + { 0xC000000C, "STATUS_TIMER_NOT_CANCELED" }, + { 0xC000000D, "STATUS_INVALID_PARAMETER" }, + { 0xC000000E, "STATUS_NO_SUCH_DEVICE" }, + { 0xC000000F, "STATUS_NO_SUCH_FILE" }, + { 0xC0000010, "STATUS_INVALID_DEVICE_REQUEST" }, + { 0xC0000011, "STATUS_END_OF_FILE" }, + { 0xC0000012, "STATUS_WRONG_VOLUME" }, + { 0xC0000013, "STATUS_NO_MEDIA_IN_DEVICE" }, + { 0xC0000014, "STATUS_UNRECOGNIZED_MEDIA" }, + { 0xC0000015, "STATUS_NONEXISTENT_SECTOR" }, + { 0xC0000016, "STATUS_MORE_PROCESSING_REQUIRED" }, + { 0xC0000017, "STATUS_NO_MEMORY" }, + { 0xC0000018, "STATUS_CONFLICTING_ADDRESSES" }, + { 0xC0000019, "STATUS_NOT_MAPPED_VIEW" }, + { 0xC000001A, "STATUS_UNABLE_TO_FREE_VM" }, + { 0xC000001B, "STATUS_UNABLE_TO_DELETE_SECTION" }, + { 0xC000001C, "STATUS_INVALID_SYSTEM_SERVICE" }, + { 0xC000001D, "STATUS_ILLEGAL_INSTRUCTION" }, + { 0xC000001E, "STATUS_INVALID_LOCK_SEQUENCE" }, + { 0xC000001F, "STATUS_INVALID_VIEW_SIZE" }, + { 0xC0000020, "STATUS_INVALID_FILE_FOR_SECTION" }, + { 0xC0000021, "STATUS_ALREADY_COMMITTED" }, + { 0xC0000022, "STATUS_ACCESS_DENIED" }, + { 0xC0000023, "STATUS_BUFFER_TOO_SMALL" }, + { 0xC0000024, "STATUS_OBJECT_TYPE_MISMATCH" }, + { 0xC0000025, "STATUS_NONCONTINUABLE_EXCEPTION" }, + { 0xC0000026, "STATUS_INVALID_DISPOSITION" }, + { 0xC0000027, "STATUS_UNWIND" }, + { 0xC0000028, "STATUS_BAD_STACK" }, + { 0xC0000029, "STATUS_INVALID_UNWIND_TARGET" }, + { 0xC000002A, "STATUS_NOT_LOCKED" }, + { 0xC000002B, "STATUS_PARITY_ERROR" }, + { 0xC000002C, "STATUS_UNABLE_TO_DECOMMIT_VM" }, + { 0xC000002D, "STATUS_NOT_COMMITTED" }, + { 0xC000002E, "STATUS_INVALID_PORT_ATTRIBUTES" }, + { 0xC000002F, "STATUS_PORT_MESSAGE_TOO_LONG" }, + { 0xC0000030, "STATUS_INVALID_PARAMETER_MIX" }, + { 0xC0000031, "STATUS_INVALID_QUOTA_LOWER" }, + { 0xC0000032, "STATUS_DISK_CORRUPT_ERROR" }, + { 0xC0000033, "STATUS_OBJECT_NAME_INVALID" }, + { 0xC0000034, "STATUS_OBJECT_NAME_NOT_FOUND" }, + { 0xC0000035, "STATUS_OBJECT_NAME_COLLISION" }, + { 0xC0000037, "STATUS_PORT_DISCONNECTED" }, + { 0xC0000038, "STATUS_DEVICE_ALREADY_ATTACHED" }, + { 0xC0000039, "STATUS_OBJECT_PATH_INVALID" }, + { 0xC000003A, "STATUS_OBJECT_PATH_NOT_FOUND" }, + { 0xC000003B, "STATUS_OBJECT_PATH_SYNTAX_BAD" }, + { 0xC000003C, "STATUS_DATA_OVERRUN" }, + { 0xC000003D, "STATUS_DATA_LATE_ERROR" }, + { 0xC000003E, "STATUS_DATA_ERROR" }, + { 0xC000003F, "STATUS_CRC_ERROR" }, + { 0xC0000040, "STATUS_SECTION_TOO_BIG" }, + { 0xC0000041, "STATUS_PORT_CONNECTION_REFUSED" }, + { 0xC0000042, "STATUS_INVALID_PORT_HANDLE" }, + { 0xC0000043, "STATUS_SHARING_VIOLATION" }, + { 0xC0000044, "STATUS_QUOTA_EXCEEDED" }, + { 0xC0000045, "STATUS_INVALID_PAGE_PROTECTION" }, + { 0xC0000046, "STATUS_MUTANT_NOT_OWNED" }, + { 0xC0000047, "STATUS_SEMAPHORE_LIMIT_EXCEEDED" }, + { 0xC0000048, "STATUS_PORT_ALREADY_SET" }, + { 0xC0000049, "STATUS_SECTION_NOT_IMAGE" }, + { 0xC000004A, "STATUS_SUSPEND_COUNT_EXCEEDED" }, + { 0xC000004B, "STATUS_THREAD_IS_TERMINATING" }, + { 0xC000004C, "STATUS_BAD_WORKING_SET_LIMIT" }, + { 0xC000004D, "STATUS_INCOMPATIBLE_FILE_MAP" }, + { 0xC000004E, "STATUS_SECTION_PROTECTION" }, + { 0xC000004F, "STATUS_EAS_NOT_SUPPORTED" }, + { 0xC0000050, "STATUS_EA_TOO_LARGE" }, + { 0xC0000051, "STATUS_NONEXISTENT_EA_ENTRY" }, + { 0xC0000052, "STATUS_NO_EAS_ON_FILE" }, + { 0xC0000053, "STATUS_EA_CORRUPT_ERROR" }, + { 0xC0000054, "STATUS_FILE_LOCK_CONFLICT" }, + { 0xC0000055, "STATUS_LOCK_NOT_GRANTED" }, + { 0xC0000056, "STATUS_DELETE_PENDING" }, + { 0xC0000057, "STATUS_CTL_FILE_NOT_SUPPORTED" }, + { 0xC0000058, "STATUS_UNKNOWN_REVISION" }, + { 0xC0000059, "STATUS_REVISION_MISMATCH" }, + { 0xC000005A, "STATUS_INVALID_OWNER" }, + { 0xC000005B, "STATUS_INVALID_PRIMARY_GROUP" }, + { 0xC000005C, "STATUS_NO_IMPERSONATION_TOKEN" }, + { 0xC000005D, "STATUS_CANT_DISABLE_MANDATORY" }, + { 0xC000005E, "STATUS_NO_LOGON_SERVERS" }, + { 0xC000005F, "STATUS_NO_SUCH_LOGON_SESSION" }, + { 0xC0000060, "STATUS_NO_SUCH_PRIVILEGE" }, + { 0xC0000061, "STATUS_PRIVILEGE_NOT_HELD" }, + { 0xC0000062, "STATUS_INVALID_ACCOUNT_NAME" }, + { 0xC0000063, "STATUS_USER_EXISTS" }, + { 0xC0000064, "STATUS_NO_SUCH_USER" }, + { 0xC0000065, "STATUS_GROUP_EXISTS" }, + { 0xC0000066, "STATUS_NO_SUCH_GROUP" }, + { 0xC0000067, "STATUS_MEMBER_IN_GROUP" }, + { 0xC0000068, "STATUS_MEMBER_NOT_IN_GROUP" }, + { 0xC0000069, "STATUS_LAST_ADMIN" }, + { 0xC000006A, "STATUS_WRONG_PASSWORD" }, + { 0xC000006B, "STATUS_ILL_FORMED_PASSWORD" }, + { 0xC000006C, "STATUS_PASSWORD_RESTRICTION" }, + { 0xC000006D, "STATUS_LOGON_FAILURE" }, + { 0xC000006E, "STATUS_ACCOUNT_RESTRICTION" }, + { 0xC000006F, "STATUS_INVALID_LOGON_HOURS" }, + { 0xC0000070, "STATUS_INVALID_WORKSTATION" }, + { 0xC0000071, "STATUS_PASSWORD_EXPIRED" }, + { 0xC0000072, "STATUS_ACCOUNT_DISABLED" }, + { 0xC0000073, "STATUS_NONE_MAPPED" }, + { 0xC0000074, "STATUS_TOO_MANY_LUIDS_REQUESTED" }, + { 0xC0000075, "STATUS_LUIDS_EXHAUSTED" }, + { 0xC0000076, "STATUS_INVALID_SUB_AUTHORITY" }, + { 0xC0000077, "STATUS_INVALID_ACL" }, + { 0xC0000078, "STATUS_INVALID_SID" }, + { 0xC0000079, "STATUS_INVALID_SECURITY_DESCR" }, + { 0xC000007A, "STATUS_PROCEDURE_NOT_FOUND" }, + { 0xC000007B, "STATUS_INVALID_IMAGE_FORMAT" }, + { 0xC000007C, "STATUS_NO_TOKEN" }, + { 0xC000007D, "STATUS_BAD_INHERITANCE_ACL" }, + { 0xC000007E, "STATUS_RANGE_NOT_LOCKED" }, + { 0xC000007F, "STATUS_DISK_FULL" }, + { 0xC0000080, "STATUS_SERVER_DISABLED" }, + { 0xC0000081, "STATUS_SERVER_NOT_DISABLED" }, + { 0xC0000082, "STATUS_TOO_MANY_GUIDS_REQUESTED" }, + { 0xC0000083, "STATUS_GUIDS_EXHAUSTED" }, + { 0xC0000084, "STATUS_INVALID_ID_AUTHORITY" }, + { 0xC0000085, "STATUS_AGENTS_EXHAUSTED" }, + { 0xC0000086, "STATUS_INVALID_VOLUME_LABEL" }, + { 0xC0000087, "STATUS_SECTION_NOT_EXTENDED" }, + { 0xC0000088, "STATUS_NOT_MAPPED_DATA" }, + { 0xC0000089, "STATUS_RESOURCE_DATA_NOT_FOUND" }, + { 0xC000008A, "STATUS_RESOURCE_TYPE_NOT_FOUND" }, + { 0xC000008B, "STATUS_RESOURCE_NAME_NOT_FOUND" }, + { 0xC000008C, "STATUS_ARRAY_BOUNDS_EXCEEDED" }, + { 0xC000008D, "STATUS_FLOAT_DENORMAL_OPERAND" }, + { 0xC000008E, "STATUS_FLOAT_DIVIDE_BY_ZERO" }, + { 0xC000008F, "STATUS_FLOAT_INEXACT_RESULT" }, + { 0xC0000090, "STATUS_FLOAT_INVALID_OPERATION" }, + { 0xC0000091, "STATUS_FLOAT_OVERFLOW" }, + { 0xC0000092, "STATUS_FLOAT_STACK_CHECK" }, + { 0xC0000093, "STATUS_FLOAT_UNDERFLOW" }, + { 0xC0000094, "STATUS_INTEGER_DIVIDE_BY_ZERO" }, + { 0xC0000095, "STATUS_INTEGER_OVERFLOW" }, + { 0xC0000096, "STATUS_PRIVILEGED_INSTRUCTION" }, + { 0xC0000097, "STATUS_TOO_MANY_PAGING_FILES" }, + { 0xC0000098, "STATUS_FILE_INVALID" }, + { 0xC0000099, "STATUS_ALLOTTED_SPACE_EXCEEDED" }, + { 0xC000009A, "STATUS_INSUFFICIENT_RESOURCES" }, + { 0xC000009B, "STATUS_DFS_EXIT_PATH_FOUND" }, + { 0xC000009C, "STATUS_DEVICE_DATA_ERROR" }, + { 0xC000009D, "STATUS_DEVICE_NOT_CONNECTED" }, + { 0xC000009E, "STATUS_DEVICE_POWER_FAILURE" }, + { 0xC000009F, "STATUS_FREE_VM_NOT_AT_BASE" }, + { 0xC00000A0, "STATUS_MEMORY_NOT_ALLOCATED" }, + { 0xC00000A1, "STATUS_WORKING_SET_QUOTA" }, + { 0xC00000A2, "STATUS_MEDIA_WRITE_PROTECTED" }, + { 0xC00000A3, "STATUS_DEVICE_NOT_READY" }, + { 0xC00000A4, "STATUS_INVALID_GROUP_ATTRIBUTES" }, + { 0xC00000A5, "STATUS_BAD_IMPERSONATION_LEVEL" }, + { 0xC00000A6, "STATUS_CANT_OPEN_ANONYMOUS" }, + { 0xC00000A7, "STATUS_BAD_VALIDATION_CLASS" }, + { 0xC00000A8, "STATUS_BAD_TOKEN_TYPE" }, + { 0xC00000A9, "STATUS_BAD_MASTER_BOOT_RECORD" }, + { 0xC00000AA, "STATUS_INSTRUCTION_MISALIGNMENT" }, + { 0xC00000AB, "STATUS_INSTANCE_NOT_AVAILABLE" }, + { 0xC00000AC, "STATUS_PIPE_NOT_AVAILABLE" }, + { 0xC00000AD, "STATUS_INVALID_PIPE_STATE" }, + { 0xC00000AE, "STATUS_PIPE_BUSY" }, + { 0xC00000AF, "STATUS_ILLEGAL_FUNCTION" }, + { 0xC00000B0, "STATUS_PIPE_DISCONNECTED" }, + { 0xC00000B1, "STATUS_PIPE_CLOSING" }, + { 0xC00000B2, "STATUS_PIPE_CONNECTED" }, + { 0xC00000B3, "STATUS_PIPE_LISTENING" }, + { 0xC00000B4, "STATUS_INVALID_READ_MODE" }, + { 0xC00000B5, "STATUS_IO_TIMEOUT" }, + { 0xC00000B6, "STATUS_FILE_FORCED_CLOSED" }, + { 0xC00000B7, "STATUS_PROFILING_NOT_STARTED" }, + { 0xC00000B8, "STATUS_PROFILING_NOT_STOPPED" }, + { 0xC00000B9, "STATUS_COULD_NOT_INTERPRET" }, + { 0xC00000BA, "STATUS_FILE_IS_A_DIRECTORY" }, + { 0xC00000BB, "STATUS_NOT_SUPPORTED" }, + { 0xC00000BC, "STATUS_REMOTE_NOT_LISTENING" }, + { 0xC00000BD, "STATUS_DUPLICATE_NAME" }, + { 0xC00000BE, "STATUS_BAD_NETWORK_PATH" }, + { 0xC00000BF, "STATUS_NETWORK_BUSY" }, + { 0xC00000C0, "STATUS_DEVICE_DOES_NOT_EXIST" }, + { 0xC00000C1, "STATUS_TOO_MANY_COMMANDS" }, + { 0xC00000C2, "STATUS_ADAPTER_HARDWARE_ERROR" }, + { 0xC00000C3, "STATUS_INVALID_NETWORK_RESPONSE" }, + { 0xC00000C4, "STATUS_UNEXPECTED_NETWORK_ERROR" }, + { 0xC00000C5, "STATUS_BAD_REMOTE_ADAPTER" }, + { 0xC00000C6, "STATUS_PRINT_QUEUE_FULL" }, + { 0xC00000C7, "STATUS_NO_SPOOL_SPACE" }, + { 0xC00000C8, "STATUS_PRINT_CANCELLED" }, + { 0xC00000C9, "STATUS_NETWORK_NAME_DELETED" }, + { 0xC00000CA, "STATUS_NETWORK_ACCESS_DENIED" }, + { 0xC00000CB, "STATUS_BAD_DEVICE_TYPE" }, + { 0xC00000CC, "STATUS_BAD_NETWORK_NAME" }, + { 0xC00000CD, "STATUS_TOO_MANY_NAMES" }, + { 0xC00000CE, "STATUS_TOO_MANY_SESSIONS" }, + { 0xC00000CF, "STATUS_SHARING_PAUSED" }, + { 0xC00000D0, "STATUS_REQUEST_NOT_ACCEPTED" }, + { 0xC00000D1, "STATUS_REDIRECTOR_PAUSED" }, + { 0xC00000D2, "STATUS_NET_WRITE_FAULT" }, + { 0xC00000D3, "STATUS_PROFILING_AT_LIMIT" }, + { 0xC00000D4, "STATUS_NOT_SAME_DEVICE" }, + { 0xC00000D5, "STATUS_FILE_RENAMED" }, + { 0xC00000D6, "STATUS_VIRTUAL_CIRCUIT_CLOSED" }, + { 0xC00000D7, "STATUS_NO_SECURITY_ON_OBJECT" }, + { 0xC00000D8, "STATUS_CANT_WAIT" }, + { 0xC00000D9, "STATUS_PIPE_EMPTY" }, + { 0xC00000DA, "STATUS_CANT_ACCESS_DOMAIN_INFO" }, + { 0xC00000DB, "STATUS_CANT_TERMINATE_SELF" }, + { 0xC00000DC, "STATUS_INVALID_SERVER_STATE" }, + { 0xC00000DD, "STATUS_INVALID_DOMAIN_STATE" }, + { 0xC00000DE, "STATUS_INVALID_DOMAIN_ROLE" }, + { 0xC00000DF, "STATUS_NO_SUCH_DOMAIN" }, + { 0xC00000E0, "STATUS_DOMAIN_EXISTS" }, + { 0xC00000E1, "STATUS_DOMAIN_LIMIT_EXCEEDED" }, + { 0xC00000E2, "STATUS_OPLOCK_NOT_GRANTED" }, + { 0xC00000E3, "STATUS_INVALID_OPLOCK_PROTOCOL" }, + { 0xC00000E4, "STATUS_INTERNAL_DB_CORRUPTION" }, + { 0xC00000E5, "STATUS_INTERNAL_ERROR" }, + { 0xC00000E6, "STATUS_GENERIC_NOT_MAPPED" }, + { 0xC00000E7, "STATUS_BAD_DESCRIPTOR_FORMAT" }, + { 0xC00000E8, "STATUS_INVALID_USER_BUFFER" }, + { 0xC00000E9, "STATUS_UNEXPECTED_IO_ERROR" }, + { 0xC00000EA, "STATUS_UNEXPECTED_MM_CREATE_ERR" }, + { 0xC00000EB, "STATUS_UNEXPECTED_MM_MAP_ERROR" }, + { 0xC00000EC, "STATUS_UNEXPECTED_MM_EXTEND_ERR" }, + { 0xC00000ED, "STATUS_NOT_LOGON_PROCESS" }, + { 0xC00000EE, "STATUS_LOGON_SESSION_EXISTS" }, + { 0xC00000EF, "STATUS_INVALID_PARAMETER_1" }, + { 0xC00000F0, "STATUS_INVALID_PARAMETER_2" }, + { 0xC00000F1, "STATUS_INVALID_PARAMETER_3" }, + { 0xC00000F2, "STATUS_INVALID_PARAMETER_4" }, + { 0xC00000F3, "STATUS_INVALID_PARAMETER_5" }, + { 0xC00000F4, "STATUS_INVALID_PARAMETER_6" }, + { 0xC00000F5, "STATUS_INVALID_PARAMETER_7" }, + { 0xC00000F6, "STATUS_INVALID_PARAMETER_8" }, + { 0xC00000F7, "STATUS_INVALID_PARAMETER_9" }, + { 0xC00000F8, "STATUS_INVALID_PARAMETER_10" }, + { 0xC00000F9, "STATUS_INVALID_PARAMETER_11" }, + { 0xC00000FA, "STATUS_INVALID_PARAMETER_12" }, + { 0xC00000FB, "STATUS_REDIRECTOR_NOT_STARTED" }, + { 0xC00000FC, "STATUS_REDIRECTOR_STARTED" }, + { 0xC00000FD, "STATUS_STACK_OVERFLOW" }, + { 0xC00000FE, "STATUS_NO_SUCH_PACKAGE" }, + { 0xC00000FF, "STATUS_BAD_FUNCTION_TABLE" }, + { 0xC0000100, "STATUS_VARIABLE_NOT_FOUND" }, + { 0xC0000101, "STATUS_DIRECTORY_NOT_EMPTY" }, + { 0xC0000102, "STATUS_FILE_CORRUPT_ERROR" }, + { 0xC0000103, "STATUS_NOT_A_DIRECTORY" }, + { 0xC0000104, "STATUS_BAD_LOGON_SESSION_STATE" }, + { 0xC0000105, "STATUS_LOGON_SESSION_COLLISION" }, + { 0xC0000106, "STATUS_NAME_TOO_LONG" }, + { 0xC0000107, "STATUS_FILES_OPEN" }, + { 0xC0000108, "STATUS_CONNECTION_IN_USE" }, + { 0xC0000109, "STATUS_MESSAGE_NOT_FOUND" }, + { 0xC000010A, "STATUS_PROCESS_IS_TERMINATING" }, + { 0xC000010B, "STATUS_INVALID_LOGON_TYPE" }, + { 0xC000010C, "STATUS_NO_GUID_TRANSLATION" }, + { 0xC000010D, "STATUS_CANNOT_IMPERSONATE" }, + { 0xC000010E, "STATUS_IMAGE_ALREADY_LOADED" }, + { 0xC000010F, "STATUS_ABIOS_NOT_PRESENT" }, + { 0xC0000110, "STATUS_ABIOS_LID_NOT_EXIST" }, + { 0xC0000111, "STATUS_ABIOS_LID_ALREADY_OWNED" }, + { 0xC0000112, "STATUS_ABIOS_NOT_LID_OWNER" }, + { 0xC0000113, "STATUS_ABIOS_INVALID_COMMAND" }, + { 0xC0000114, "STATUS_ABIOS_INVALID_LID" }, + { 0xC0000115, "STATUS_ABIOS_SELECTOR_NOT_AVAILABLE" }, + { 0xC0000116, "STATUS_ABIOS_INVALID_SELECTOR" }, + { 0xC0000117, "STATUS_NO_LDT" }, + { 0xC0000118, "STATUS_INVALID_LDT_SIZE" }, + { 0xC0000119, "STATUS_INVALID_LDT_OFFSET" }, + { 0xC000011A, "STATUS_INVALID_LDT_DESCRIPTOR" }, + { 0xC000011B, "STATUS_INVALID_IMAGE_NE_FORMAT" }, + { 0xC000011C, "STATUS_RXACT_INVALID_STATE" }, + { 0xC000011D, "STATUS_RXACT_COMMIT_FAILURE" }, + { 0xC000011E, "STATUS_MAPPED_FILE_SIZE_ZERO" }, + { 0xC000011F, "STATUS_TOO_MANY_OPENED_FILES" }, + { 0xC0000120, "STATUS_CANCELLED" }, + { 0xC0000121, "STATUS_CANNOT_DELETE" }, + { 0xC0000122, "STATUS_INVALID_COMPUTER_NAME" }, + { 0xC0000123, "STATUS_FILE_DELETED" }, + { 0xC0000124, "STATUS_SPECIAL_ACCOUNT" }, + { 0xC0000125, "STATUS_SPECIAL_GROUP" }, + { 0xC0000126, "STATUS_SPECIAL_USER" }, + { 0xC0000127, "STATUS_MEMBERS_PRIMARY_GROUP" }, + { 0xC0000128, "STATUS_FILE_CLOSED" }, + { 0xC0000129, "STATUS_TOO_MANY_THREADS" }, + { 0xC000012A, "STATUS_THREAD_NOT_IN_PROCESS" }, + { 0xC000012B, "STATUS_TOKEN_ALREADY_IN_USE" }, + { 0xC000012C, "STATUS_PAGEFILE_QUOTA_EXCEEDED" }, + { 0xC000012D, "STATUS_COMMITMENT_LIMIT" }, + { 0xC000012E, "STATUS_INVALID_IMAGE_LE_FORMAT" }, + { 0xC000012F, "STATUS_INVALID_IMAGE_NOT_MZ" }, + { 0xC0000130, "STATUS_INVALID_IMAGE_PROTECT" }, + { 0xC0000131, "STATUS_INVALID_IMAGE_WIN_16" }, + { 0xC0000132, "STATUS_LOGON_SERVER_CONFLICT" }, + { 0xC0000133, "STATUS_TIME_DIFFERENCE_AT_DC" }, + { 0xC0000134, "STATUS_SYNCHRONIZATION_REQUIRED" }, + { 0xC0000135, "STATUS_DLL_NOT_FOUND" }, + { 0xC0000136, "STATUS_OPEN_FAILED" }, + { 0xC0000137, "STATUS_IO_PRIVILEGE_FAILED" }, + { 0xC0000138, "STATUS_ORDINAL_NOT_FOUND" }, + { 0xC0000139, "STATUS_ENTRYPOINT_NOT_FOUND" }, + { 0xC000013A, "STATUS_CONTROL_C_EXIT" }, + { 0xC000013B, "STATUS_LOCAL_DISCONNECT" }, + { 0xC000013C, "STATUS_REMOTE_DISCONNECT" }, + { 0xC000013D, "STATUS_REMOTE_RESOURCES" }, + { 0xC000013E, "STATUS_LINK_FAILED" }, + { 0xC000013F, "STATUS_LINK_TIMEOUT" }, + { 0xC0000140, "STATUS_INVALID_CONNECTION" }, + { 0xC0000141, "STATUS_INVALID_ADDRESS" }, + { 0xC0000142, "STATUS_DLL_INIT_FAILED" }, + { 0xC0000143, "STATUS_MISSING_SYSTEMFILE" }, + { 0xC0000144, "STATUS_UNHANDLED_EXCEPTION" }, + { 0xC0000145, "STATUS_APP_INIT_FAILURE" }, + { 0xC0000146, "STATUS_PAGEFILE_CREATE_FAILED" }, + { 0xC0000147, "STATUS_NO_PAGEFILE" }, + { 0xC0000148, "STATUS_INVALID_LEVEL" }, + { 0xC0000149, "STATUS_WRONG_PASSWORD_CORE" }, + { 0xC000014A, "STATUS_ILLEGAL_FLOAT_CONTEXT" }, + { 0xC000014B, "STATUS_PIPE_BROKEN" }, + { 0xC000014C, "STATUS_REGISTRY_CORRUPT" }, + { 0xC000014D, "STATUS_REGISTRY_IO_FAILED" }, + { 0xC000014E, "STATUS_NO_EVENT_PAIR" }, + { 0xC000014F, "STATUS_UNRECOGNIZED_VOLUME" }, + { 0xC0000150, "STATUS_SERIAL_NO_DEVICE_INITED" }, + { 0xC0000151, "STATUS_NO_SUCH_ALIAS" }, + { 0xC0000152, "STATUS_MEMBER_NOT_IN_ALIAS" }, + { 0xC0000153, "STATUS_MEMBER_IN_ALIAS" }, + { 0xC0000154, "STATUS_ALIAS_EXISTS" }, + { 0xC0000155, "STATUS_LOGON_NOT_GRANTED" }, + { 0xC0000156, "STATUS_TOO_MANY_SECRETS" }, + { 0xC0000157, "STATUS_SECRET_TOO_LONG" }, + { 0xC0000158, "STATUS_INTERNAL_DB_ERROR" }, + { 0xC0000159, "STATUS_FULLSCREEN_MODE" }, + { 0xC000015A, "STATUS_TOO_MANY_CONTEXT_IDS" }, + { 0xC000015B, "STATUS_LOGON_TYPE_NOT_GRANTED" }, + { 0xC000015C, "STATUS_NOT_REGISTRY_FILE" }, + { 0xC000015D, "STATUS_NT_CROSS_ENCRYPTION_REQUIRED" }, + { 0xC000015E, "STATUS_DOMAIN_CTRLR_CONFIG_ERROR" }, + { 0xC000015F, "STATUS_FT_MISSING_MEMBER" }, + { 0xC0000160, "STATUS_ILL_FORMED_SERVICE_ENTRY" }, + { 0xC0000161, "STATUS_ILLEGAL_CHARACTER" }, + { 0xC0000162, "STATUS_UNMAPPABLE_CHARACTER" }, + { 0xC0000163, "STATUS_UNDEFINED_CHARACTER" }, + { 0xC0000164, "STATUS_FLOPPY_VOLUME" }, + { 0xC0000165, "STATUS_FLOPPY_ID_MARK_NOT_FOUND" }, + { 0xC0000166, "STATUS_FLOPPY_WRONG_CYLINDER" }, + { 0xC0000167, "STATUS_FLOPPY_UNKNOWN_ERROR" }, + { 0xC0000168, "STATUS_FLOPPY_BAD_REGISTERS" }, + { 0xC0000169, "STATUS_DISK_RECALIBRATE_FAILED" }, + { 0xC000016A, "STATUS_DISK_OPERATION_FAILED" }, + { 0xC000016B, "STATUS_DISK_RESET_FAILED" }, + { 0xC000016C, "STATUS_SHARED_IRQ_BUSY" }, + { 0xC000016D, "STATUS_FT_ORPHANING" }, + { 0xC000016E, "STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT" }, + { 0xC0000172, "STATUS_PARTITION_FAILURE" }, + { 0xC0000173, "STATUS_INVALID_BLOCK_LENGTH" }, + { 0xC0000174, "STATUS_DEVICE_NOT_PARTITIONED" }, + { 0xC0000175, "STATUS_UNABLE_TO_LOCK_MEDIA" }, + { 0xC0000176, "STATUS_UNABLE_TO_UNLOAD_MEDIA" }, + { 0xC0000177, "STATUS_EOM_OVERFLOW" }, + { 0xC0000178, "STATUS_NO_MEDIA" }, + { 0xC000017A, "STATUS_NO_SUCH_MEMBER" }, + { 0xC000017B, "STATUS_INVALID_MEMBER" }, + { 0xC000017C, "STATUS_KEY_DELETED" }, + { 0xC000017D, "STATUS_NO_LOG_SPACE" }, + { 0xC000017E, "STATUS_TOO_MANY_SIDS" }, + { 0xC000017F, "STATUS_LM_CROSS_ENCRYPTION_REQUIRED" }, + { 0xC0000180, "STATUS_KEY_HAS_CHILDREN" }, + { 0xC0000181, "STATUS_CHILD_MUST_BE_VOLATILE" }, + { 0xC0000182, "STATUS_DEVICE_CONFIGURATION_ERROR" }, + { 0xC0000183, "STATUS_DRIVER_INTERNAL_ERROR" }, + { 0xC0000184, "STATUS_INVALID_DEVICE_STATE" }, + { 0xC0000185, "STATUS_IO_DEVICE_ERROR" }, + { 0xC0000186, "STATUS_DEVICE_PROTOCOL_ERROR" }, + { 0xC0000187, "STATUS_BACKUP_CONTROLLER" }, + { 0xC0000188, "STATUS_LOG_FILE_FULL" }, + { 0xC0000189, "STATUS_TOO_LATE" }, + { 0xC000018A, "STATUS_NO_TRUST_LSA_SECRET" }, + { 0xC000018B, "STATUS_NO_TRUST_SAM_ACCOUNT" }, + { 0xC000018C, "STATUS_TRUSTED_DOMAIN_FAILURE" }, + { 0xC000018D, "STATUS_TRUSTED_RELATIONSHIP_FAILURE" }, + { 0xC000018E, "STATUS_EVENTLOG_FILE_CORRUPT" }, + { 0xC000018F, "STATUS_EVENTLOG_CANT_START" }, + { 0xC0000190, "STATUS_TRUST_FAILURE" }, + { 0xC0000191, "STATUS_MUTANT_LIMIT_EXCEEDED" }, + { 0xC0000192, "STATUS_NETLOGON_NOT_STARTED" }, + { 0xC0000193, "STATUS_ACCOUNT_EXPIRED" }, + { 0xC0000194, "STATUS_POSSIBLE_DEADLOCK" }, + { 0xC0000195, "STATUS_NETWORK_CREDENTIAL_CONFLICT" }, + { 0xC0000196, "STATUS_REMOTE_SESSION_LIMIT" }, + { 0xC0000197, "STATUS_EVENTLOG_FILE_CHANGED" }, + { 0xC0000198, "STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT" }, + { 0xC0000199, "STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT" }, + { 0xC000019A, "STATUS_NOLOGON_SERVER_TRUST_ACCOUNT" }, + { 0xC000019B, "STATUS_DOMAIN_TRUST_INCONSISTENT" }, + { 0xC000019C, "STATUS_FS_DRIVER_REQUIRED" }, + { 0xC0000202, "STATUS_NO_USER_SESSION_KEY" }, + { 0xC0000203, "STATUS_USER_SESSION_DELETED" }, + { 0xC0000204, "STATUS_RESOURCE_LANG_NOT_FOUND" }, + { 0xC0000205, "STATUS_INSUFF_SERVER_RESOURCES" }, + { 0xC0000206, "STATUS_INVALID_BUFFER_SIZE" }, + { 0xC0000207, "STATUS_INVALID_ADDRESS_COMPONENT" }, + { 0xC0000208, "STATUS_INVALID_ADDRESS_WILDCARD" }, + { 0xC0000209, "STATUS_TOO_MANY_ADDRESSES" }, + { 0xC000020A, "STATUS_ADDRESS_ALREADY_EXISTS" }, + { 0xC000020B, "STATUS_ADDRESS_CLOSED" }, + { 0xC000020C, "STATUS_CONNECTION_DISCONNECTED" }, + { 0xC000020D, "STATUS_CONNECTION_RESET" }, + { 0xC000020E, "STATUS_TOO_MANY_NODES" }, + { 0xC000020F, "STATUS_TRANSACTION_ABORTED" }, + { 0xC0000210, "STATUS_TRANSACTION_TIMED_OUT" }, + { 0xC0000211, "STATUS_TRANSACTION_NO_RELEASE" }, + { 0xC0000212, "STATUS_TRANSACTION_NO_MATCH" }, + { 0xC0000213, "STATUS_TRANSACTION_RESPONDED" }, + { 0xC0000214, "STATUS_TRANSACTION_INVALID_ID" }, + { 0xC0000215, "STATUS_TRANSACTION_INVALID_TYPE" }, + { 0xC0000216, "STATUS_NOT_SERVER_SESSION" }, + { 0xC0000217, "STATUS_NOT_CLIENT_SESSION" }, + { 0xC0000218, "STATUS_CANNOT_LOAD_REGISTRY_FILE" }, + { 0xC0000219, "STATUS_DEBUG_ATTACH_FAILED" }, + { 0xC000021A, "STATUS_SYSTEM_PROCESS_TERMINATED" }, + { 0xC000021B, "STATUS_DATA_NOT_ACCEPTED" }, + { 0xC000021C, "STATUS_NO_BROWSER_SERVERS_FOUND" }, + { 0xC000021D, "STATUS_VDM_HARD_ERROR" }, + { 0xC000021E, "STATUS_DRIVER_CANCEL_TIMEOUT" }, + { 0xC000021F, "STATUS_REPLY_MESSAGE_MISMATCH" }, + { 0xC0000220, "STATUS_MAPPED_ALIGNMENT" }, + { 0xC0000221, "STATUS_IMAGE_CHECKSUM_MISMATCH" }, + { 0xC0000222, "STATUS_LOST_WRITEBEHIND_DATA" }, + { 0xC0000223, "STATUS_CLIENT_SERVER_PARAMETERS_INVALID" }, + { 0xC0000224, "STATUS_PASSWORD_MUST_CHANGE" }, + { 0xC0000225, "STATUS_NOT_FOUND" }, + { 0xC0000226, "STATUS_NOT_TINY_STREAM" }, + { 0xC0000227, "STATUS_RECOVERY_FAILURE" }, + { 0xC0000228, "STATUS_STACK_OVERFLOW_READ" }, + { 0xC0000229, "STATUS_FAIL_CHECK" }, + { 0xC000022A, "STATUS_DUPLICATE_OBJECTID" }, + { 0xC000022B, "STATUS_OBJECTID_EXISTS" }, + { 0xC000022C, "STATUS_CONVERT_TO_LARGE" }, + { 0xC000022D, "STATUS_RETRY" }, + { 0xC000022E, "STATUS_FOUND_OUT_OF_SCOPE" }, + { 0xC000022F, "STATUS_ALLOCATE_BUCKET" }, + { 0xC0000230, "STATUS_PROPSET_NOT_FOUND" }, + { 0xC0000231, "STATUS_MARSHALL_OVERFLOW" }, + { 0xC0000232, "STATUS_INVALID_VARIANT" }, + { 0xC0000233, "STATUS_DOMAIN_CONTROLLER_NOT_FOUND" }, + { 0xC0000234, "STATUS_ACCOUNT_LOCKED_OUT" }, + { 0xC0000235, "STATUS_HANDLE_NOT_CLOSABLE" }, + { 0xC0000236, "STATUS_CONNECTION_REFUSED" }, + { 0xC0000237, "STATUS_GRACEFUL_DISCONNECT" }, + { 0xC0000238, "STATUS_ADDRESS_ALREADY_ASSOCIATED" }, + { 0xC0000239, "STATUS_ADDRESS_NOT_ASSOCIATED" }, + { 0xC000023A, "STATUS_CONNECTION_INVALID" }, + { 0xC000023B, "STATUS_CONNECTION_ACTIVE" }, + { 0xC000023C, "STATUS_NETWORK_UNREACHABLE" }, + { 0xC000023D, "STATUS_HOST_UNREACHABLE" }, + { 0xC000023E, "STATUS_PROTOCOL_UNREACHABLE" }, + { 0xC000023F, "STATUS_PORT_UNREACHABLE" }, + { 0xC0000240, "STATUS_REQUEST_ABORTED" }, + { 0xC0000241, "STATUS_CONNECTION_ABORTED" }, + { 0xC0000242, "STATUS_BAD_COMPRESSION_BUFFER" }, + { 0xC0000243, "STATUS_USER_MAPPED_FILE" }, + { 0xC0000244, "STATUS_AUDIT_FAILED" }, + { 0xC0000245, "STATUS_TIMER_RESOLUTION_NOT_SET" }, + { 0xC0000246, "STATUS_CONNECTION_COUNT_LIMIT" }, + { 0xC0000247, "STATUS_LOGIN_TIME_RESTRICTION" }, + { 0xC0000248, "STATUS_LOGIN_WKSTA_RESTRICTION" }, + { 0xC0000249, "STATUS_IMAGE_MP_UP_MISMATCH" }, + { 0xC0000250, "STATUS_INSUFFICIENT_LOGON_INFO" }, + { 0xC0000251, "STATUS_BAD_DLL_ENTRYPOINT" }, + { 0xC0000252, "STATUS_BAD_SERVICE_ENTRYPOINT" }, + { 0xC0000253, "STATUS_LPC_REPLY_LOST" }, + { 0xC0000254, "STATUS_IP_ADDRESS_CONFLICT1" }, + { 0xC0000255, "STATUS_IP_ADDRESS_CONFLICT2" }, + { 0xC0000256, "STATUS_REGISTRY_QUOTA_LIMIT" }, + { 0xC0000257, "STATUS_PATH_NOT_COVERED" }, + { 0xC0000258, "STATUS_NO_CALLBACK_ACTIVE" }, + { 0xC0000259, "STATUS_LICENSE_QUOTA_EXCEEDED" }, + { 0xC000025A, "STATUS_PWD_TOO_SHORT" }, + { 0xC000025B, "STATUS_PWD_TOO_RECENT" }, + { 0xC000025C, "STATUS_PWD_HISTORY_CONFLICT" }, + { 0xC000025E, "STATUS_PLUGPLAY_NO_DEVICE" }, + { 0xC000025F, "STATUS_UNSUPPORTED_COMPRESSION" }, + { 0xC0000260, "STATUS_INVALID_HW_PROFILE" }, + { 0xC0000261, "STATUS_INVALID_PLUGPLAY_DEVICE_PATH" }, + { 0xC0000262, "STATUS_DRIVER_ORDINAL_NOT_FOUND" }, + { 0xC0000263, "STATUS_DRIVER_ENTRYPOINT_NOT_FOUND" }, + { 0xC0000264, "STATUS_RESOURCE_NOT_OWNED" }, + { 0xC0000265, "STATUS_TOO_MANY_LINKS" }, + { 0xC0000266, "STATUS_QUOTA_LIST_INCONSISTENT" }, + { 0xC0000267, "STATUS_FILE_IS_OFFLINE" }, + { 0xC0000268, "STATUS_EVALUATION_EXPIRATION" }, + { 0xC0000269, "STATUS_ILLEGAL_DLL_RELOCATION" }, + { 0xC000026A, "STATUS_LICENSE_VIOLATION" }, + { 0xC000026B, "STATUS_DLL_INIT_FAILED_LOGOFF" }, + { 0xC000026C, "STATUS_DRIVER_UNABLE_TO_LOAD" }, + { 0xC000026D, "STATUS_DFS_UNAVAILABLE" }, + { 0xC000026E, "STATUS_VOLUME_DISMOUNTED" }, + { 0xC000026F, "STATUS_WX86_INTERNAL_ERROR" }, + { 0xC0000270, "STATUS_WX86_FLOAT_STACK_CHECK" }, + { 0xC0000271, "STATUS_VALIDATE_CONTINUE" }, + { 0xC0000272, "STATUS_NO_MATCH" }, + { 0xC0000273, "STATUS_NO_MORE_MATCHES" }, + { 0xC0000275, "STATUS_NOT_A_REPARSE_POINT" }, + { 0xC0000276, "STATUS_IO_REPARSE_TAG_INVALID" }, + { 0xC0000277, "STATUS_IO_REPARSE_TAG_MISMATCH" }, + { 0xC0000278, "STATUS_IO_REPARSE_DATA_INVALID" }, + { 0xC0000279, "STATUS_IO_REPARSE_TAG_NOT_HANDLED" }, + { 0xC0000280, "STATUS_REPARSE_POINT_NOT_RESOLVED" }, + { 0xC0000281, "STATUS_DIRECTORY_IS_A_REPARSE_POINT" }, + { 0xC0000282, "STATUS_RANGE_LIST_CONFLICT" }, + { 0xC0000283, "STATUS_SOURCE_ELEMENT_EMPTY" }, + { 0xC0000284, "STATUS_DESTINATION_ELEMENT_FULL" }, + { 0xC0000285, "STATUS_ILLEGAL_ELEMENT_ADDRESS" }, + { 0xC0000286, "STATUS_MAGAZINE_NOT_PRESENT" }, + { 0xC0000287, "STATUS_REINITIALIZATION_NEEDED" }, + { 0x80000288, "STATUS_DEVICE_REQUIRES_CLEANING" }, + { 0x80000289, "STATUS_DEVICE_DOOR_OPEN" }, + { 0xC000028A, "STATUS_ENCRYPTION_FAILED" }, + { 0xC000028B, "STATUS_DECRYPTION_FAILED" }, + { 0xC000028C, "STATUS_RANGE_NOT_FOUND" }, + { 0xC000028D, "STATUS_NO_RECOVERY_POLICY" }, + { 0xC000028E, "STATUS_NO_EFS" }, + { 0xC000028F, "STATUS_WRONG_EFS" }, + { 0xC0000290, "STATUS_NO_USER_KEYS" }, + { 0xC0000291, "STATUS_FILE_NOT_ENCRYPTED" }, + { 0xC0000292, "STATUS_NOT_EXPORT_FORMAT" }, + { 0xC0000293, "STATUS_FILE_ENCRYPTED" }, + { 0x40000294, "STATUS_WAKE_SYSTEM" }, + { 0xC0000295, "STATUS_WMI_GUID_NOT_FOUND" }, + { 0xC0000296, "STATUS_WMI_INSTANCE_NOT_FOUND" }, + { 0xC0000297, "STATUS_WMI_ITEMID_NOT_FOUND" }, + { 0xC0000298, "STATUS_WMI_TRY_AGAIN" }, + { 0xC0000299, "STATUS_SHARED_POLICY" }, + { 0xC000029A, "STATUS_POLICY_OBJECT_NOT_FOUND" }, + { 0xC000029B, "STATUS_POLICY_ONLY_IN_DS" }, + { 0xC000029C, "STATUS_VOLUME_NOT_UPGRADED" }, + { 0xC000029D, "STATUS_REMOTE_STORAGE_NOT_ACTIVE" }, + { 0xC000029E, "STATUS_REMOTE_STORAGE_MEDIA_ERROR" }, + { 0xC000029F, "STATUS_NO_TRACKING_SERVICE" }, + { 0xC00002A0, "STATUS_SERVER_SID_MISMATCH" }, + { 0xC00002A1, "STATUS_DS_NO_ATTRIBUTE_OR_VALUE" }, + { 0xC00002A2, "STATUS_DS_INVALID_ATTRIBUTE_SYNTAX" }, + { 0xC00002A3, "STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED" }, + { 0xC00002A4, "STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS" }, + { 0xC00002A5, "STATUS_DS_BUSY" }, + { 0xC00002A6, "STATUS_DS_UNAVAILABLE" }, + { 0xC00002A7, "STATUS_DS_NO_RIDS_ALLOCATED" }, + { 0xC00002A8, "STATUS_DS_NO_MORE_RIDS" }, + { 0xC00002A9, "STATUS_DS_INCORRECT_ROLE_OWNER" }, + { 0xC00002AA, "STATUS_DS_RIDMGR_INIT_ERROR" }, + { 0xC00002AB, "STATUS_DS_OBJ_CLASS_VIOLATION" }, + { 0xC00002AC, "STATUS_DS_CANT_ON_NON_LEAF" }, + { 0xC00002AD, "STATUS_DS_CANT_ON_RDN" }, + { 0xC00002AE, "STATUS_DS_CANT_MOD_OBJ_CLASS" }, + { 0xC00002AF, "STATUS_DS_CROSS_DOM_MOVE_FAILED" }, + { 0xC00002B0, "STATUS_DS_GC_NOT_AVAILABLE" }, + { 0xC00002B1, "STATUS_DIRECTORY_SERVICE_REQUIRED" }, + { 0xC00002B2, "STATUS_REPARSE_ATTRIBUTE_CONFLICT" }, + { 0xC00002B3, "STATUS_CANT_ENABLE_DENY_ONLY" }, + { 0xC00002B4, "STATUS_FLOAT_MULTIPLE_FAULTS" }, + { 0xC00002B5, "STATUS_FLOAT_MULTIPLE_TRAPS" }, + { 0xC00002B6, "STATUS_DEVICE_REMOVED" }, + { 0xC00002B7, "STATUS_JOURNAL_DELETE_IN_PROGRESS" }, + { 0xC00002B8, "STATUS_JOURNAL_NOT_ACTIVE" }, + { 0xC00002B9, "STATUS_NOINTERFACE" }, + { 0xC00002C1, "STATUS_DS_ADMIN_LIMIT_EXCEEDED" }, + { 0xC00002C2, "STATUS_DRIVER_FAILED_SLEEP" }, + { 0xC00002C3, "STATUS_MUTUAL_AUTHENTICATION_FAILED" }, + { 0xC00002C4, "STATUS_CORRUPT_SYSTEM_FILE" }, + { 0xC00002C5, "STATUS_DATATYPE_MISALIGNMENT_ERROR" }, + { 0xC00002C6, "STATUS_WMI_READ_ONLY" }, + { 0xC00002C7, "STATUS_WMI_SET_FAILURE" }, + { 0xC00002C8, "STATUS_COMMITMENT_MINIMUM" }, + { 0xC00002C9, "STATUS_REG_NAT_CONSUMPTION" }, + { 0xC00002CA, "STATUS_TRANSPORT_FULL" }, + { 0xC00002CB, "STATUS_DS_SAM_INIT_FAILURE" }, + { 0xC00002CC, "STATUS_ONLY_IF_CONNECTED" }, + { 0xC00002CD, "STATUS_DS_SENSITIVE_GROUP_VIOLATION" }, + { 0xC00002CE, "STATUS_PNP_RESTART_ENUMERATION" }, + { 0xC00002CF, "STATUS_JOURNAL_ENTRY_DELETED" }, + { 0xC00002D0, "STATUS_DS_CANT_MOD_PRIMARYGROUPID" }, + { 0xC00002D1, "STATUS_SYSTEM_IMAGE_BAD_SIGNATURE" }, + { 0xC00002D2, "STATUS_PNP_REBOOT_REQUIRED" }, + { 0xC00002D3, "STATUS_POWER_STATE_INVALID" }, + { 0xC00002D4, "STATUS_DS_INVALID_GROUP_TYPE" }, + { 0xC00002D5, "STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN" }, + { 0xC00002D6, "STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN" }, + { 0xC00002D7, "STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER" }, + { 0xC00002D8, "STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER" }, + { 0xC00002D9, "STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER" }, + { 0xC00002DA, "STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER" }, + { 0xC00002DB, "STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER" }, + { 0xC00002DC, "STATUS_DS_HAVE_PRIMARY_MEMBERS" }, + { 0xC00002DD, "STATUS_WMI_NOT_SUPPORTED" }, + { 0xC00002DE, "STATUS_INSUFFICIENT_POWER" }, + { 0xC00002DF, "STATUS_SAM_NEED_BOOTKEY_PASSWORD" }, + { 0xC00002E0, "STATUS_SAM_NEED_BOOTKEY_FLOPPY" }, + { 0xC00002E1, "STATUS_DS_CANT_START" }, + { 0xC00002E2, "STATUS_DS_INIT_FAILURE" }, + { 0xC00002E3, "STATUS_SAM_INIT_FAILURE" }, + { 0xC00002E4, "STATUS_DS_GC_REQUIRED" }, + { 0xC00002E5, "STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY" }, + { 0xC00002E6, "STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS" }, + { 0xC00002E7, "STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED" }, + { 0xC00002E8, "STATUS_MULTIPLE_FAULT_VIOLATION" }, + { 0xC0000300, "STATUS_NOT_SUPPORTED_ON_SBS" }, + { 0xC0009898, "STATUS_WOW_ASSERTION" }, + { 0xC0020001, "RPC_NT_INVALID_STRING_BINDING" }, + { 0xC0020002, "RPC_NT_WRONG_KIND_OF_BINDING" }, + { 0xC0020003, "RPC_NT_INVALID_BINDING" }, + { 0xC0020004, "RPC_NT_PROTSEQ_NOT_SUPPORTED" }, + { 0xC0020005, "RPC_NT_INVALID_RPC_PROTSEQ" }, + { 0xC0020006, "RPC_NT_INVALID_STRING_UUID" }, + { 0xC0020007, "RPC_NT_INVALID_ENDPOINT_FORMAT" }, + { 0xC0020008, "RPC_NT_INVALID_NET_ADDR" }, + { 0xC0020009, "RPC_NT_NO_ENDPOINT_FOUND" }, + { 0xC002000A, "RPC_NT_INVALID_TIMEOUT" }, + { 0xC002000B, "RPC_NT_OBJECT_NOT_FOUND" }, + { 0xC002000C, "RPC_NT_ALREADY_REGISTERED" }, + { 0xC002000D, "RPC_NT_TYPE_ALREADY_REGISTERED" }, + { 0xC002000E, "RPC_NT_ALREADY_LISTENING" }, + { 0xC002000F, "RPC_NT_NO_PROTSEQS_REGISTERED" }, + { 0xC0020010, "RPC_NT_NOT_LISTENING" }, + { 0xC0020011, "RPC_NT_UNKNOWN_MGR_TYPE" }, + { 0xC0020012, "RPC_NT_UNKNOWN_IF" }, + { 0xC0020013, "RPC_NT_NO_BINDINGS" }, + { 0xC0020014, "RPC_NT_NO_PROTSEQS" }, + { 0xC0020015, "RPC_NT_CANT_CREATE_ENDPOINT" }, + { 0xC0020016, "RPC_NT_OUT_OF_RESOURCES" }, + { 0xC0020017, "RPC_NT_SERVER_UNAVAILABLE" }, + { 0xC0020018, "RPC_NT_SERVER_TOO_BUSY" }, + { 0xC0020019, "RPC_NT_INVALID_NETWORK_OPTIONS" }, + { 0xC002001A, "RPC_NT_NO_CALL_ACTIVE" }, + { 0xC002001B, "RPC_NT_CALL_FAILED" }, + { 0xC002001C, "RPC_NT_CALL_FAILED_DNE" }, + { 0xC002001D, "RPC_NT_PROTOCOL_ERROR" }, + { 0xC002001F, "RPC_NT_UNSUPPORTED_TRANS_SYN" }, + { 0xC0020021, "RPC_NT_UNSUPPORTED_TYPE" }, + { 0xC0020022, "RPC_NT_INVALID_TAG" }, + { 0xC0020023, "RPC_NT_INVALID_BOUND" }, + { 0xC0020024, "RPC_NT_NO_ENTRY_NAME" }, + { 0xC0020025, "RPC_NT_INVALID_NAME_SYNTAX" }, + { 0xC0020026, "RPC_NT_UNSUPPORTED_NAME_SYNTAX" }, + { 0xC0020028, "RPC_NT_UUID_NO_ADDRESS" }, + { 0xC0020029, "RPC_NT_DUPLICATE_ENDPOINT" }, + { 0xC002002A, "RPC_NT_UNKNOWN_AUTHN_TYPE" }, + { 0xC002002B, "RPC_NT_MAX_CALLS_TOO_SMALL" }, + { 0xC002002C, "RPC_NT_STRING_TOO_LONG" }, + { 0xC002002D, "RPC_NT_PROTSEQ_NOT_FOUND" }, + { 0xC002002E, "RPC_NT_PROCNUM_OUT_OF_RANGE" }, + { 0xC002002F, "RPC_NT_BINDING_HAS_NO_AUTH" }, + { 0xC0020030, "RPC_NT_UNKNOWN_AUTHN_SERVICE" }, + { 0xC0020031, "RPC_NT_UNKNOWN_AUTHN_LEVEL" }, + { 0xC0020032, "RPC_NT_INVALID_AUTH_IDENTITY" }, + { 0xC0020033, "RPC_NT_UNKNOWN_AUTHZ_SERVICE" }, + { 0xC0020034, "EPT_NT_INVALID_ENTRY" }, + { 0xC0020035, "EPT_NT_CANT_PERFORM_OP" }, + { 0xC0020036, "EPT_NT_NOT_REGISTERED" }, + { 0xC0020037, "RPC_NT_NOTHING_TO_EXPORT" }, + { 0xC0020038, "RPC_NT_INCOMPLETE_NAME" }, + { 0xC0020039, "RPC_NT_INVALID_VERS_OPTION" }, + { 0xC002003A, "RPC_NT_NO_MORE_MEMBERS" }, + { 0xC002003B, "RPC_NT_NOT_ALL_OBJS_UNEXPORTED" }, + { 0xC002003C, "RPC_NT_INTERFACE_NOT_FOUND" }, + { 0xC002003D, "RPC_NT_ENTRY_ALREADY_EXISTS" }, + { 0xC002003E, "RPC_NT_ENTRY_NOT_FOUND" }, + { 0xC002003F, "RPC_NT_NAME_SERVICE_UNAVAILABLE" }, + { 0xC0020040, "RPC_NT_INVALID_NAF_ID" }, + { 0xC0020041, "RPC_NT_CANNOT_SUPPORT" }, + { 0xC0020042, "RPC_NT_NO_CONTEXT_AVAILABLE" }, + { 0xC0020043, "RPC_NT_INTERNAL_ERROR" }, + { 0xC0020044, "RPC_NT_ZERO_DIVIDE" }, + { 0xC0020045, "RPC_NT_ADDRESS_ERROR" }, + { 0xC0020046, "RPC_NT_FP_DIV_ZERO" }, + { 0xC0020047, "RPC_NT_FP_UNDERFLOW" }, + { 0xC0020048, "RPC_NT_FP_OVERFLOW" }, + { 0xC0021007, "RPC_P_RECEIVE_ALERTED" }, + { 0xC0021008, "RPC_P_CONNECTION_CLOSED" }, + { 0xC0021009, "RPC_P_RECEIVE_FAILED" }, + { 0xC002100A, "RPC_P_SEND_FAILED" }, + { 0xC002100B, "RPC_P_TIMEOUT" }, + { 0xC002100C, "RPC_P_SERVER_TRANSPORT_ERROR" }, + { 0xC002100E, "RPC_P_EXCEPTION_OCCURED" }, + { 0xC0021012, "RPC_P_CONNECTION_SHUTDOWN" }, + { 0xC0021015, "RPC_P_THREAD_LISTENING" }, + { 0xC0030001, "RPC_NT_NO_MORE_ENTRIES" }, + { 0xC0030002, "RPC_NT_SS_CHAR_TRANS_OPEN_FAIL" }, + { 0xC0030003, "RPC_NT_SS_CHAR_TRANS_SHORT_FILE" }, + { 0xC0030004, "RPC_NT_SS_IN_NULL_CONTEXT" }, + { 0xC0030005, "RPC_NT_SS_CONTEXT_MISMATCH" }, + { 0xC0030006, "RPC_NT_SS_CONTEXT_DAMAGED" }, + { 0xC0030007, "RPC_NT_SS_HANDLES_MISMATCH" }, + { 0xC0030008, "RPC_NT_SS_CANNOT_GET_CALL_HANDLE" }, + { 0xC0030009, "RPC_NT_NULL_REF_POINTER" }, + { 0xC003000A, "RPC_NT_ENUM_VALUE_OUT_OF_RANGE" }, + { 0xC003000B, "RPC_NT_BYTE_COUNT_TOO_SMALL" }, + { 0xC003000C, "RPC_NT_BAD_STUB_DATA" }, + { 0xC0020049, "RPC_NT_CALL_IN_PROGRESS" }, + { 0xC002004A, "RPC_NT_NO_MORE_BINDINGS" }, + { 0xC002004B, "RPC_NT_GROUP_MEMBER_NOT_FOUND" }, + { 0xC002004C, "EPT_NT_CANT_CREATE" }, + { 0xC002004D, "RPC_NT_INVALID_OBJECT" }, + { 0xC002004F, "RPC_NT_NO_INTERFACES" }, + { 0xC0020050, "RPC_NT_CALL_CANCELLED" }, + { 0xC0020051, "RPC_NT_BINDING_INCOMPLETE" }, + { 0xC0020052, "RPC_NT_COMM_FAILURE" }, + { 0xC0020053, "RPC_NT_UNSUPPORTED_AUTHN_LEVEL" }, + { 0xC0020054, "RPC_NT_NO_PRINC_NAME" }, + { 0xC0020055, "RPC_NT_NOT_RPC_ERROR" }, + { 0x40020056, "RPC_NT_UUID_LOCAL_ONLY" }, + { 0xC0020057, "RPC_NT_SEC_PKG_ERROR" }, + { 0xC0020058, "RPC_NT_NOT_CANCELLED" }, + { 0xC0030059, "RPC_NT_INVALID_ES_ACTION" }, + { 0xC003005A, "RPC_NT_WRONG_ES_VERSION" }, + { 0xC003005B, "RPC_NT_WRONG_STUB_VERSION" }, + { 0xC003005C, "RPC_NT_INVALID_PIPE_OBJECT" }, + { 0xC003005D, "RPC_NT_INVALID_PIPE_OPERATION" }, + { 0xC003005E, "RPC_NT_WRONG_PIPE_VERSION" }, + { 0x400200AF, "RPC_NT_SEND_INCOMPLETE" }, + { 0, NULL } +}; + +#endif /* __VALUE_STRING_H__ */ + +#endif /* _NTSTATUS_ */ diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/os_calls.c posixrdp/posixxrdp.orig/common/os_calls.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/os_calls.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/os_calls.c 2010-11-08 09:56:43.000000000 +0100 @@ -1,5 +1,5 @@ /* - Copyright (c) 2004-2010 Jay Sorg + Copyright (c) 2004-2009 Jay Sorg Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -35,17 +35,21 @@ #if defined(sun) || defined(__sun) #define ctid_t id_t #endif +#include #include #include +#include +#include #include #include -#include #include +#include #include #include #include #include #include +#include #include #include #include @@ -56,19 +60,39 @@ #include #endif +#if defined(__linux__) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif + + +#include #include #include #include #include #include +/* #include */ +#include "/usr/include/iconv.h" #include "os_calls.h" #include "arch.h" +#include "stringlist.h" +#include "dbg.h" /* for clearenv() */ #if defined(_WIN32) #else -extern char** environ; +extern char ** environ; #endif /* for solaris */ @@ -79,6 +103,10 @@ #define INADDR_NONE ((unsigned long)-1) #endif +static iconv_t g_icd = (iconv_t)(-1); +static iconv_t g_ocd = (iconv_t)(-1); +static pthread_mutex_t g_mutex_iconv; + /*****************************************************************************/ void APP_CC g_init(void) @@ -106,20 +134,20 @@ void* APP_CC g_malloc(int size, int zero) { - char* rv; - - rv = (char*)malloc(size); - if (zero) - { - if (rv != 0) - { - memset(rv, 0, size); - } + void * rv = (void *)NULL; + if (size > 0) { + rv = (zero > 0) ? (void *)calloc(size,1) : (void *)malloc(size); } return rv; } /*****************************************************************************/ +void * APP_CC +g_realloc(void * ptr, int size) { + return (ptr == NULL || size < 1) ? (void *)NULL : (void *)realloc(ptr, size); +} + +/*****************************************************************************/ /* free the memory pointed to by ptr, ptr can be zero */ void APP_CC g_free(void* ptr) @@ -134,7 +162,7 @@ /* output text to stdout, try to use g_write / g_writeln instead to avoid linux / windows EOL problems */ void DEFAULT_CC -g_printf(const char* format, ...) +g_printf(const char * format, ...) { va_list ap; @@ -145,7 +173,7 @@ /*****************************************************************************/ void DEFAULT_CC -g_sprintf(char* dest, const char* format, ...) +g_sprintf(char * dest, const char * format, ...) { va_list ap; @@ -156,7 +184,7 @@ /*****************************************************************************/ void DEFAULT_CC -g_snprintf(char* dest, int len, const char* format, ...) +g_snprintf(char * dest, size_t len, const char * format, ...) { va_list ap; @@ -166,8 +194,18 @@ } /*****************************************************************************/ +int DEFAULT_CC +g_scnprintf(char * buf, size_t size, const char *fmt, ...) { + va_list args; + int rv = 0; + + rv = vsnprintf(buf,size,fmt,args); + return (rv >= size) ? (size - 1) : rv; +} + +/*****************************************************************************/ void DEFAULT_CC -g_writeln(const char* format, ...) +g_writeln(const char * format, ...) { va_list ap; @@ -183,7 +221,7 @@ /*****************************************************************************/ void DEFAULT_CC -g_write(const char* format, ...) +g_write(const char * format, ...) { va_list ap; @@ -193,16 +231,70 @@ } /*****************************************************************************/ +void DEFAULT_CC +g_lfile_writeln(FILE *trg, const char * format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(trg, format, ap); + va_end(ap); +#if defined(_WIN32) + fprintf(trg, "\r\n"); +#else + fprintf(trg, "\n"); +#endif +} + +/*****************************************************************************/ +void DEFAULT_CC +g_lfile_write(FILE *trg, const char * format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(trg, format, ap); + va_end(ap); +} + +/*****************************************************************************/ +void DEFAULT_CC +g_writeln_err(const char * format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); +#if defined(_WIN32) + g_printf("\r\n"); +#else + g_printf("\n"); +#endif +} + +/*****************************************************************************/ +void DEFAULT_CC +g_write_err(const char * format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); +} + +/*****************************************************************************/ /* produce a hex dump */ void APP_CC -g_hexdump(char* p, int len) +g_hexdump(const char * p, size_t len) { - unsigned char* line; - int i; - int thisline; - int offset; + unsigned char * line = (unsigned char *)NULL; + ptrdiff_t i = 0; + int thisline = 0; + ptrdiff_t offset = 0; - line = (unsigned char*)p; + line = (unsigned char *)p; offset = 0; while (offset < len) { @@ -231,15 +323,64 @@ } /*****************************************************************************/ +/* produce a hex dump */ +void APP_CC +g_fhexdump(char * f, char * p, size_t len) +{ + unsigned char * line = (unsigned char *)NULL; + ptrdiff_t i = 0; + int thisline = 0; + ptrdiff_t offset = 0; + FILE *fp = (FILE *)NULL; + + if (f==NULL) { + f = g_malloc(sizeof(char), (strlen("/tmp/hexdump") + 1)); + strcpy(f,"/tmp/hexdump"); + } + + fp = fopen(f,"a"); + + line = (unsigned char *)p; + offset = 0; + while (offset < len) + { + fprintf(fp, "%04x ", offset); + thisline = len - offset; + if (thisline > 16) + { + thisline = 16; + } + for (i = 0; i < thisline; i++) + { + fprintf(fp,"%02x ", line[i]); + } + for (; i < 16; i++) + { + fprintf(fp," "); + } + for (i = 0; i < thisline; i++) + { + fprintf(fp,"%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.'); + } + /* g_writeln(""); */ + fprintf(fp, "\n\n**********\n"); + offset += thisline; + line += thisline; + } + + fclose(fp); +} + +/*****************************************************************************/ void APP_CC -g_memset(void* ptr, int val, int size) +g_memset(void* ptr, int val, size_t size) { memset(ptr, val, size); } /*****************************************************************************/ void APP_CC -g_memcpy(void* d_ptr, const void* s_ptr, int size) +g_memcpy(void* d_ptr, const void* s_ptr, size_t size) { memcpy(d_ptr, s_ptr, size); } @@ -253,26 +394,25 @@ /*****************************************************************************/ int APP_CC -g_tcp_set_no_delay(int sck) +g_tcp_set_no_delay(tbus sck) { + int option_value = 0; #if defined(_WIN32) - int option_value; - int option_len; + int option_len = 0; #else - int option_value; - unsigned int option_len; + unsigned int option_len = 0; #endif option_len = sizeof(option_value); /* SOL_TCP IPPROTO_TCP */ - if (getsockopt(sck, IPPROTO_TCP, TCP_NODELAY, (char*)&option_value, + if (getsockopt(sck, IPPROTO_TCP, TCP_NODELAY, (char *)&option_value, &option_len) == 0) { if (option_value == 0) { option_value = 1; option_len = sizeof(option_value); - setsockopt(sck, IPPROTO_TCP, TCP_NODELAY, (char*)&option_value, + setsockopt(sck, IPPROTO_TCP, TCP_NODELAY, (char *)&option_value, option_len); } } @@ -284,46 +424,65 @@ int APP_CC g_tcp_socket(void) { + int rv = 0; + int option_value = 0; + /* in win32 a socket is an unsigned int, in linux, its an int */ #if defined(_WIN32) - int rv; - int option_value; - int option_len; + int option_len = 0; #else - int rv; - int option_value; - unsigned int option_len; + unsigned int option_len = 0; #endif - /* in win32 a socket is an unsigned int, in linux, its an int */ - rv = (int)socket(PF_INET, SOCK_STREAM, 0); +#ifdef _XRDP_ENABLE_IPv6_ + rv = (int)socket(AF_INET6, SOCK_STREAM, 0); +#else + rv = (int)socket(AF_INET, SOCK_STREAM, 0); +#endif if (rv < 0) { - return -1; + rv = -1; } - option_len = sizeof(option_value); - if (getsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (char*)&option_value, - &option_len) == 0) - { - if (option_value == 0) + else { +#ifdef _XRDP_ENABLE_IPv6_ + option_len = sizeof(option_value); + if (getsockopt(rv, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&option_value, + &option_len) == 0) { - option_value = 1; - option_len = sizeof(option_value); - setsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (char*)&option_value, - option_len); + if (option_value != 0) + { + option_value = 0; + option_len = sizeof(option_value); + setsockopt(rv, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&option_value, + option_len); + } } - } - option_len = sizeof(option_value); - if (getsockopt(rv, SOL_SOCKET, SO_SNDBUF, (char*)&option_value, - &option_len) == 0) - { - if (option_value < (1024 * 32)) +#endif + option_len = sizeof(option_value); + if (getsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (char *)&option_value, + &option_len) == 0) { - option_value = 1024 * 32; - option_len = sizeof(option_value); - setsockopt(rv, SOL_SOCKET, SO_SNDBUF, (char*)&option_value, - option_len); + if (option_value == 0) + { + option_value = 1; + option_len = sizeof(option_value); + setsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (char *)&option_value, + option_len); + } + } + option_len = sizeof(option_value); + if (getsockopt(rv, SOL_SOCKET, SO_SNDBUF, (char *)&option_value, + &option_len) == 0) + { + if (option_value < (1024 * 32)) + { + option_value = 1024 * 32; + option_len = sizeof(option_value); + setsockopt(rv, SOL_SOCKET, SO_SNDBUF, (char *)&option_value, + option_len); + } } } + MDBGLOG("chansrv","INFO\t[%s()]: done (rv = %d).",__func__,rv); return rv; } @@ -331,6 +490,7 @@ int APP_CC g_tcp_local_socket(void) { + MDBGLOG("net","INFO\t[%s()]: called",__func__); #if defined(_WIN32) return 0; #else @@ -339,77 +499,111 @@ } /*****************************************************************************/ -void APP_CC -g_tcp_close(int sck) +int APP_CC +g_socketpair(int * fds) { - if (sck == 0) + MDBGLOG("net","INFO\t[%s()]: called",__func__); +#if defined(_WIN32) + return 0; +#else + return socketpair(PF_LOCAL, SOCK_STREAM, 0, fds); +#endif +} + +/*****************************************************************************/ +void APP_CC +g_tcp_close(tbus sck) { + MDBGLOG("net","INFO\t[%s()]: called (sck = %d)",__func__,sck); + if (sck != 0) { - return; - } - shutdown(sck, 2); + shutdown(sck, 2); #if defined(_WIN32) - closesocket(sck); + closesocket(sck); #else - close(sck); + close(sck); #endif + } + MDBGLOG("net","INFO\t[%s()]: done.",__func__); } /*****************************************************************************/ /* returns error, zero is good */ int APP_CC -g_tcp_connect(int sck, const char* address, const char* port) +g_tcp_connect(tbus sck, const char * address, const char * port) { - struct sockaddr_in s; - struct hostent* h; - - g_memset(&s, 0, sizeof(struct sockaddr_in)); - s.sin_family = AF_INET; - s.sin_port = htons((tui16)atoi(port)); - s.sin_addr.s_addr = inet_addr(address); - if (s.sin_addr.s_addr == INADDR_NONE) - { - h = gethostbyname(address); - if (h != 0) - { - if (h->h_name != 0) - { - if (h->h_addr_list != 0) - { - if ((*(h->h_addr_list)) != 0) - { - s.sin_addr.s_addr = *((int*)(*(h->h_addr_list))); - } - } + int res = 0; + struct addrinfo p; + struct addrinfo *h = (struct addrinfo *)NULL; + struct addrinfo *rp = (struct addrinfo *)NULL; + + /* initialize (zero out) local variables: */ + g_memset(&p,0,sizeof(struct addrinfo)); + + /* in IPv6-enabled environments, set the AI_V4MAPPED + * flag in ai_flags and specify ai_family=AF_INET6 in + * order to ensure that getaddrinfo() returns any + * available IPv4-mapped addresses in case the target + * host does not have a true IPv6 address: + */ +#ifdef _XRDP_ENABLE_IPv6_ + p.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED; + p.ai_family = AF_INET6; +#else + p.ai_flags = AI_ADDRCONFIG; + p.ai_family = AF_INET; +#endif + p.ai_socktype = SOCK_STREAM; + p.ai_protocol = IPPROTO_TCP; + res = getaddrinfo(address,port,&p,&h); + if (res > -1) { + if (h != NULL) { + for (rp = h; rp != NULL; rp = rp->ai_next) { + rp = h; + res = connect(sck, (struct sockaddr *)(rp->ai_addr), rp->ai_addrlen); + if (res != -1) { + break; /* Success */ + } } } } - return connect(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in)); + return res; } /*****************************************************************************/ /* returns error, zero is good */ int APP_CC -g_tcp_local_connect(int sck, const char* port) +g_tcp_local_connect(tbus sck, const char * port) { + MDBGLOG("net","INFO\t[%s()]: called (port = \"%s\")",__func__,((port == NULL || g_strlen(port) < 1)?"(none)":port)); #if defined(_WIN32) return -1; #else - struct sockaddr_un s; + size_t len = 0; + struct sockaddr_un * s = (struct sockaddr_un *)NULL; - memset(&s, 0, sizeof(struct sockaddr_un)); - s.sun_family = AF_UNIX; - strcpy(s.sun_path, port); - return connect(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_un)); + s = (struct sockaddr_un *)g_malloc(sizeof(struct sockaddr_un), 1); + if (s != NULL) { + s->sun_family = AF_UNIX; + g_strncpy(s->sun_path, port, 104); + len = sizeof(s->sun_family) + g_strlen(s->sun_path); + MDBGLOG("net","INFO\t[%s()]: done.",__func__); + return connect(sck, (const struct sockaddr *)s, len); + } + else { + MDBGLOG("net","ERROR\t[%s()]: out of memory",__func__); + return -ENOMEM; + } #endif } /*****************************************************************************/ int APP_CC -g_tcp_set_non_blocking(int sck) +g_tcp_set_non_blocking(tbus sck) { - unsigned long i; + unsigned long i = 0; -#if defined(_WIN32) + MDBGLOG("net","INFO\t[%s()]: called (sck = %d)",__func__,sck); +#ifdef _WIN32 i = 1; ioctlsocket(sck, FIONBIO, &i); #else @@ -417,165 +611,393 @@ i = i | O_NONBLOCK; fcntl(sck, F_SETFL, i); #endif + MDBGLOG("net","INFO\t[%s()]: done.",__func__); return 0; } /*****************************************************************************/ -/* returns error, zero is good */ int APP_CC -g_tcp_bind(int sck, char* port) +g_tcp_set_blocking(tbus sck) { - struct sockaddr_in s; + unsigned long i = 0; + + MDBGLOG("net","INFO\t[%s()]: called (sck = %d)",__func__,sck); +#ifdef _WIN32 + i = 1; + ioctlsocket(sck, FIONBIO, &i); +#else + i = fcntl(sck, F_GETFL); + i &= ~O_NONBLOCK; + fcntl(sck, F_SETFL, i); +#endif + MDBGLOG("net","INFO\t[%s()]: done.",__func__); + return 0; +} - memset(&s, 0, sizeof(struct sockaddr_in)); - s.sin_family = AF_INET; - s.sin_port = htons((tui16)atoi(port)); - s.sin_addr.s_addr = INADDR_ANY; - return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in)); +/*****************************************************************************/ +int APP_CC +g_fifo_set_blocking(tbus fd) { + int rv = 0; +#ifdef _WIN32 + rv = -EINVAL; +#else + uint32_t i = 0; + const uint32_t nb = O_NONBLOCK; + + MDBGLOG("net","INFO\t[%s()]: called (fd = %d)",__func__,fd); + + if (fd < 1) { + rv = -EINVAL; + } + else { + i = fcntl(fd, F_GETFL); + if ((i & nb) > 0) { + i = i ^ nb; + } + fcntl(fd, F_SETFL, i); + } +#endif + MDBGLOG("net","INFO\t[%s()]: done (rv = %d).",__func__,rv); + return rv; } + /*****************************************************************************/ +/* returns error, zero is good */ int APP_CC -g_tcp_local_bind(int sck, char* port) -{ -#if defined(_WIN32) - return -1; +g_tcp_bind_flags(tbus sck, const char * port, int flags) { + int res = -1; + int error = 0; +#ifdef _XRDP_ENABLE_IPv6_ + int ipv4 = 0; +#endif + struct addrinfo hints; + struct addrinfo * i = (struct addrinfo *)NULL; + struct addrinfo * j = (struct addrinfo *)NULL; + + /* initialize (zero out) local variables: */ + g_memset(&hints, 0, sizeof(hints)); + + hints.ai_family = AF_UNSPEC; + hints.ai_flags = flags; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + error = getaddrinfo(NULL,port,&hints,&i); + if (error) { + res = -1; + } + else { + /* iterate the entire list returned by getaddrinfo() + * and determine how many IPv6 and IPv4 addresses, respectively, + * are available: + */ + j = i; +#ifdef _XRDP_ENABLE_IPv6_ + while (j && (res < 0)) { + if (j->ai_family == PF_INET6) { + res = bind(sck, (struct sockaddr *)j->ai_addr, j->ai_addrlen); + } + else { + ipv4++; + } + j = j->ai_next; + } + if ((res < 0) && (ipv4 > 0)) { + j = i; + while (j && (res < 0)) { + if (j->ai_family != PF_INET6) { + res = bind(sck, (struct sockaddr *)j->ai_addr, j->ai_addrlen); + } + j = j->ai_next; + } + } #else - struct sockaddr_un s; + while (j && (res < 0)) { + res = bind(sck, (struct sockaddr *)j->ai_addr, j->ai_addrlen); + j = j->ai_next; + } +#endif + } + + return res; +} + + +/*****************************************************************************/ +/* returns error, zero is good */ +int APP_CC +g_tcp_bind(tbus sck, const char * port) { + const int flags = AI_ADDRCONFIG; + return g_tcp_bind_flags(sck, port, flags); +} + - memset(&s, 0, sizeof(struct sockaddr_un)); - s.sun_family = AF_UNIX; - strcpy(s.sun_path, port); - return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_un)); +/*****************************************************************************/ +int APP_CC +g_tcp_local_bind(tbus sck, const char * port) { + int rv = 0; +#if defined(_WIN32) + rv = -EINVAL; +#else + if (sck < 1 || port == NULL || g_strlen(port) < 1) { + rv = -EINVAL; + } + else { + size_t len = 0; + struct sockaddr_un ls; + struct sockaddr_un * s = &ls; + g_memset(s,0,sizeof(struct sockaddr_un)); + s->sun_family = AF_UNIX; + g_strncpy(s->sun_path, port, sizeof(s->sun_path)); + len = sizeof(struct sockaddr_un); + rv = bind(sck, (const struct sockaddr *)s, len); + } #endif + return rv; } /*****************************************************************************/ /* returns error, zero is good */ int APP_CC -g_tcp_listen(int sck) +g_tcp_listen(tbus sck) { return listen(sck, 2); } /*****************************************************************************/ int APP_CC -g_tcp_accept(int sck) +g_tcp_accept(tbus sck) { - struct sockaddr_in s; + struct sockaddr_storage s; #if defined(_WIN32) - signed int i; + signed int i = 0; #else - unsigned int i; + unsigned int i = 0; #endif - - i = sizeof(struct sockaddr_in); - memset(&s, 0, i); + i = sizeof(struct sockaddr_storage); + g_memset(&s,0,i); return accept(sck, (struct sockaddr*)&s, &i); } /*****************************************************************************/ void APP_CC -g_sleep(int msecs) +g_sleep(uint64_t msecs) { #if defined(_WIN32) Sleep(msecs); #else - usleep(msecs * 1000); + useconds_t us = 0; + us += msecs; + us *= 1000; + usleep(us); +#endif +} + +/*****************************************************************************/ +void APP_CC +g_usleep(uint64_t usecs) +{ +#if defined(_WIN32) +#else + usleep(usecs); #endif } /*****************************************************************************/ int APP_CC -g_tcp_last_error_would_block(int sck) +g_tcp_last_error_would_block(tbus sck) { #if defined(_WIN32) return WSAGetLastError() == WSAEWOULDBLOCK; #else - return (errno == EWOULDBLOCK) || (errno == EAGAIN) || (errno == EINPROGRESS); + return (errno == EWOULDBLOCK) || (errno == EINPROGRESS); #endif } /*****************************************************************************/ -int APP_CC -g_tcp_recv(int sck, void* ptr, int len, int flags) +size_t APP_CC +g_tcp_recv(tbus sck, void * ptr, size_t len, int flags) { #if defined(_WIN32) - return recv(sck, (char*)ptr, len, flags); + return recv(sck, (char *)ptr, len, flags); +#else + size_t rv = 0; + + if (sck == 0 || ptr == NULL || len < 0) { + rv = 0; + } + else if (len == 0) { + rv = 0; + } + else { + rv = recv(sck, ptr, len, flags); + } + return rv; + +#endif +} + +/*****************************************************************************/ +size_t APP_CC +g_fifo_read(tbus fd, void * ptr, size_t len) +{ + size_t rv = 0; + + if (fd == 0 || ptr == NULL || len < 0) { + rv = 0; + } + else if (len == 0) { + rv = 0; + } + else { + rv = read(fd, ptr, len); + } + return rv; +} + +/*****************************************************************************/ +size_t APP_CC +g_fifo_write(tbus fd, const void * ptr, size_t len) +{ + size_t rv = 0; + + if (fd == 0 || ptr == NULL || len < 0) { + rv = 0; + } + else if (len == 0) { + rv = 0; + } + else { +#ifdef _WIN32 + rv = write(fd, (const char *)ptr, len); #else - return recv(sck, ptr, len, flags); + rv = write(fd, ptr, len); #endif + } + return rv; } /*****************************************************************************/ -int APP_CC -g_tcp_send(int sck, const void* ptr, int len, int flags) +size_t APP_CC +g_tcp_send(tbus sck, const void* ptr, size_t len, int flags) { + if (sck > -1 && ptr != NULL && len > 0 && g_tcp_socket_ok(sck)) { #if defined(_WIN32) - return send(sck, (const char*)ptr, len, flags); + return (size_t)(send(sck, (const char *)ptr, len, flags)); #else - return send(sck, ptr, len, flags); + return (size_t)(send(sck, ptr, len, flags)); #endif + } + else { + return 0; + } +} + +/*****************************************************************************/ +size_t APP_CC +g_tcp_send_force(tbus sck, const void * ptr, size_t len, int flags) +{ + size_t rv = 0; + size_t rem = len; + if (sck > -1 && ptr != NULL && len > 0) { + while (rem > 0) { + if (0 && !g_tcp_socket_ok(sck)) { + rv = 0; + break; + } + else if (g_tcp_can_send(sck, 300)) { +#if defined(_WIN32) + rem -= (size_t)(send(sck, (const char *)ptr, len, flags)); +#else + rem -= (size_t)(send(sck, ptr, len, flags)); +#endif + } + } + rv = len; + } + return rv; } /*****************************************************************************/ /* returns boolean */ int APP_CC -g_tcp_socket_ok(int sck) +g_tcp_socket_ok(tbus sck) { + int res = 0; + int opt = 0; #if defined(_WIN32) - int opt; - int opt_len; + int opt_len = 0; #else - int opt; - unsigned int opt_len; + unsigned int opt_len = 0; #endif - opt_len = sizeof(opt); - if (getsockopt(sck, SOL_SOCKET, SO_ERROR, (char*)(&opt), &opt_len) == 0) - { - if (opt == 0) + if (sck < 0) { + res = 0; + } + else { + opt_len = sizeof(opt); + if (getsockopt(sck, SOL_SOCKET, SO_ERROR, (char *)(&opt), &opt_len) == 0) { - return 1; + if (opt == 0) + { + res = 1; + } } } - return 0; + return res; } /*****************************************************************************/ /* wait 'millis' milliseconds for the socket to be able to write */ /* returns boolean */ int APP_CC -g_tcp_can_send(int sck, int millis) -{ +g_tcp_can_send(tbus sck, int millis) { fd_set wfds; struct timeval time; - int rv; + int rv = 0; + + if (sck < 1) { + rv = 0; + goto end; + } + + //DBGLOG("net","[os_calls]->g_tcp_can_send() called"); + g_memset(&wfds,0,sizeof(fd_set)); + g_memset(&time,0,sizeof(struct timeval)); time.tv_sec = millis / 1000; time.tv_usec = (millis * 1000) % 1000000; FD_ZERO(&wfds); - if (sck > 0) - { + if (sck > 0) { FD_SET(((unsigned int)sck), &wfds); rv = select(sck + 1, 0, &wfds, 0, &time); if (rv > 0) { - return g_tcp_socket_ok(sck); + rv = g_tcp_socket_ok(sck); + } + else + { + rv = 0; } } - return 0; + + end:; + return rv; } /*****************************************************************************/ /* wait 'millis' milliseconds for the socket to be able to receive */ /* returns boolean */ int APP_CC -g_tcp_can_recv(int sck, int millis) +g_tcp_can_recv(tbus sck, int millis) { fd_set rfds; struct timeval time; - int rv; + int rv = 0; + int res = 0; + + g_memset(&time,0,sizeof(struct timeval)); + g_memset(&rfds,0,sizeof(fd_set)); time.tv_sec = millis / 1000; time.tv_usec = (millis * 1000) % 1000000; @@ -586,20 +1008,60 @@ rv = select(sck + 1, &rfds, 0, 0, &time); if (rv > 0) { - return g_tcp_socket_ok(sck); + res = g_tcp_socket_ok(sck); + } + else + { + res = 0; } } - return 0; + return res; } /*****************************************************************************/ +/* wait 'millis' milliseconds for the FIFO to be able to receive */ +/* returns boolean */ int APP_CC -g_tcp_select(int sck1, int sck2) +g_fifo_can_read(tbus fd, int millis) { fd_set rfds; struct timeval time; - int max; - int rv; + int rv = 0; + int res = 0; + + g_memset(&time,0,sizeof(struct timeval)); + g_memset(&rfds,0,sizeof(fd_set)); + + time.tv_sec = millis / 1000; + time.tv_usec = (millis * 1000) % 1000000; + FD_ZERO(&rfds); + if (fd > -1) + { + FD_SET(((unsigned int)fd), &rfds); + rv = select(fd + 1, &rfds, 0, 0, &time); + if (rv > 0) + { + res = 1; + } + else + { + res = 0; + } + } + return res; +} + +/*****************************************************************************/ +int APP_CC +g_tcp_select(tbus sck1, tbus sck2) +{ + fd_set rfds; + struct timeval time; + int max = 0; + int rv = 0; + + g_memset(&rfds,0,sizeof(fd_set)); + g_memset(&time,0,sizeof(struct timeval)); time.tv_sec = 0; time.tv_usec = 0; @@ -640,49 +1102,104 @@ /*****************************************************************************/ /* returns 0 on error */ tbus APP_CC -g_create_wait_obj(char* name) +g_create_wait_obj(const char * name) { -#ifdef _WIN32 - tbus obj; + tbus obj = (tbus)(-1); +#ifdef _WIN32 obj = (tbus)CreateEvent(0, 1, 0, name); return obj; #else - tbus obj; struct sockaddr_un sa; - int len; - int sck; - int i; + size_t len = 0; + tbus sck = -1; + int i = 0; - sck = socket(PF_UNIX, SOCK_DGRAM, 0); + MDBGLOG("net","INFO\t[%s()]: called (name = %s)",__func__,name); + g_memset(&sa,0,sizeof(struct sockaddr_un)); + + sck = socket(PF_LOCAL, SOCK_DGRAM, 0); if (sck < 0) { return 0; } - memset(&sa, 0, sizeof(sa)); - sa.sun_family = AF_UNIX; + sa.sun_family = AF_LOCAL; if ((name == 0) || (strlen(name) == 0)) { - g_random((char*)&i, sizeof(i)); + g_random((char *)&i, sizeof(i)); sprintf(sa.sun_path, "/tmp/auto%8.8x", i); - while (g_file_exist(sa.sun_path)) - { - g_random((char*)&i, sizeof(i)); + while (g_file_exist(sa.sun_path)) { + g_random((char *)&i, sizeof(i)); sprintf(sa.sun_path, "/tmp/auto%8.8x", i); } } else { - sprintf(sa.sun_path, "/tmp/%s", name); + g_sprintf(sa.sun_path, "/tmp/%s", name); + } + unlink(sa.sun_path); + len = sizeof(sa); + if (bind(sck, (const struct sockaddr *)&sa, len) < 0) + { + MDBGLOG("net","ERROR\t[%s()]: bind() failed",__func__); + close(sck); + return 0; + } + obj = (tbus)sck; + + MDBGLOG("net","INFO\t[%s()]: done (obj = %d).",__func__,sck); + return obj; +#endif +} + +/*****************************************************************************/ +/* returns 0 on error */ +tbus APP_CC +g_create_wait_obj_from_path(const char * path) { + tbus obj = (tbus)(-1); + +#ifdef _WIN32 + obj = (tbus)CreateEvent(0, 1, 0, name); + return obj; +#else + struct sockaddr_un sa; + size_t len = 0; + tbus sck = -1; + int i = 0; + + MDBGLOG("net","INFO\t[%s()]: called (path = %s)",__func__,path); + g_memset(&sa,0,sizeof(struct sockaddr_un)); + + sck = socket(PF_LOCAL, SOCK_DGRAM, 0); + if (sck < 0) + { + return 0; + } + sa.sun_family = AF_LOCAL; + if ((path == 0) || (strlen(path) == 0)) + { + g_random((char *)&i, sizeof(i)); + g_snprintf(sa.sun_path, sizeof(sa.sun_path), "/tmp/auto%8.8x", i); + while (g_file_exist(sa.sun_path)) { + g_random((char *)&i, sizeof(i)); + g_snprintf(sa.sun_path, sizeof(sa.sun_path), "/tmp/auto%8.8x", i); + } + } + else + { + g_snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", path); } unlink(sa.sun_path); len = sizeof(sa); - if (bind(sck, (struct sockaddr*)&sa, len) < 0) + if (bind(sck, (const struct sockaddr *)&sa, len) < 0) { + MDBGLOG("net","ERROR\t[%s()]: bind() failed",__func__); close(sck); return 0; } obj = (tbus)sck; + + MDBGLOG("net","INFO\t[%s()]: done (obj = %d).",__func__,sck); return obj; #endif } @@ -695,7 +1212,9 @@ #ifdef _WIN32 /* Create and return corresponding event handle for WaitForMultipleObjets */ WSAEVENT event; - long lnetevent; + long lnetevent = 0; + + g_memset(&event,0,sizeof(WSAEVENT)); event = WSACreateEvent(); lnetevent = (write ? FD_WRITE : FD_READ) | FD_CLOSE; @@ -708,14 +1227,107 @@ return 0; } #else + MDBGLOG("net","INFO\t[%s()]: done (socket = %d; write = %d)",__func__,(int)socket,write); + return socket; #endif } /*****************************************************************************/ +/* returns 0 on error */ +tbus APP_CC +g_create_wait_obj_from_fifo(tbus fifo, int write) +{ +#ifdef _WIN32 + /* Create and return corresponding event handle for WaitForMultipleObjets */ + WSAEVENT event; + long lnetevent = 0; + + g_memset(&event,0,sizeof(WSAEVENT)); + + event = WSACreateEvent(); + lnetevent = (write ? FD_WRITE : FD_READ) | FD_CLOSE; + if (WSAEventSelect(fifo, event, lnetevent) == 0) + { + return (tbus)event; + } + else + { + return 0; + } +#else + MDBGLOG("net","INFO\t[%s()]: called (fifo FD = %d; write = %d)",__func__,(int)fifo,write); + + return fifo; +#endif +} + +/*****************************************************************************/ +/* returns -1 on error, else return handle or file descriptor */ +int APP_CC +g_create_fifo(const char * file_name) { +#if defined(_WIN32) + return (int)CreateFileA(file_name, GENERIC_READ, + FILE_SHARE_READ, + 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); +#else + int rv = 0; + MDBGLOG("net","INFO\t[%s()]: called (file_name = %s)",__func__,file_name); + if (file_name == NULL || g_strlen(file_name) < 1) { + rv = -1; + } + else { + g_file_delete(file_name); + rv = g_mkfifo(file_name, 0666); + } + MDBGLOG("net","INFO\t[%s()]: called (rv = %d).",__func__,rv); + return rv; +#endif +} + +/*****************************************************************************/ +/* returns -1 on error, else return handle or file descriptor */ +int APP_CC +g_create_selfpipe(const char * file_name) +{ +#if defined(_WIN32) + return (int)CreateFileA(file_name, GENERIC_READ, + FILE_SHARE_READ, + 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); +#else + int rv = 0; + + MDBGLOG("net","INFO\t[%s()]: called (file_name = %s)",__func__,file_name); + + rv = g_mkfifo(file_name, 0666); + + /* The following statement works correctly under Linux, + * but its behavior is non-standard (the POSIX standard + * does not define what occurs when a FIFO is opened + * with the O_RDWR flag). + */ + rv = open(file_name, O_RDWR | O_NDELAY); + + /* If the non-standard method does not work, then the + * following method is more POSIX-compliant; however, it + * may be susceptible to a potential race condition. + */ + if (rv < 0) { + rv = open(file_name, O_RDONLY); + rv = open(file_name, O_WRONLY); + } + + MDBGLOG("net","INFO\t[%s()]: done (rv = %d)",__func__,rv); + + return rv; +#endif +} + +/*****************************************************************************/ void APP_CC g_delete_wait_obj_from_socket(tbus wait_obj) { + MDBGLOG("net","INFO\t[%s()]: called (wait_obj = %d)",__func__,wait_obj); #ifdef _WIN32 if (wait_obj == 0) { @@ -737,12 +1349,13 @@ return 0; } SetEvent((HANDLE)obj); - return 0; #else socklen_t sa_size; int s; struct sockaddr_un sa; + //MDBGLOG("net","INFO\t[%s()]: called (obj = %d)",__func__,(int)obj); + if (obj == 0) { return 0; @@ -757,15 +1370,15 @@ { return 1; } - s = socket(PF_UNIX, SOCK_DGRAM, 0); + s = socket(PF_LOCAL, SOCK_DGRAM, 0); if (s < 0) { return 1; } sendto(s, "sig", 4, 0, (struct sockaddr*)&sa, sa_size); close(s); - return 0; #endif + return 0; } /*****************************************************************************/ @@ -773,26 +1386,25 @@ int APP_CC g_reset_wait_obj(tbus obj) { + int rv = 0; + if (obj != 0) { #ifdef _WIN32 - if (obj == 0) - { - return 0; - } - ResetEvent((HANDLE)obj); - return 0; + ResetEvent((HANDLE)obj); #else - char buf[64]; - - if (obj == 0) - { - return 0; - } - while (g_tcp_can_recv((int)obj, 0)) - { - recvfrom((int)obj, &buf, 64, 0, 0, 0); - } - return 0; + char buf[64]; + struct stat finfo; + g_memset(&finfo,0,sizeof(struct stat)); + fstat((int)obj, &finfo); + if (S_ISFIFO(finfo.st_mode) || S_ISREG(finfo.st_mode) || S_ISCHR(finfo.st_mode)) while (g_fifo_can_read((int)obj, 0)) { + g_fifo_read((int)obj, buf, 64);//qqq + } + else if (S_ISSOCK(finfo.st_mode)) while (g_tcp_can_recv((int)obj, 0)) { + g_tcp_recv(obj, buf, 64, 0); + //recvfrom((int)obj, buf, 64, 0, 0, 0); + } #endif + } + return rv; } /*****************************************************************************/ @@ -811,11 +1423,26 @@ } return 0; #else - if (obj == 0) - { - return 0; + int rv = 0; + struct stat finfo; + g_memset(&finfo,0,sizeof(struct stat)); + if (obj == 0) { + rv = 0; } - return g_tcp_can_recv((int)obj, 0); + else { + fstat((int)obj, &finfo); + if (S_ISFIFO(finfo.st_mode) || S_ISREG(finfo.st_mode) || S_ISCHR(finfo.st_mode)) { + rv = g_fifo_can_read((int)obj, 0); + } + else if (S_ISSOCK(finfo.st_mode)) { + rv = g_tcp_can_recv((int)obj, 0); + } + else { + MDBGLOG("net","ERROR\t[%s()]: unrecognized FD type (finfo.st_mode = %d)",__func__,finfo.st_mode); + rv = -1; + } + } + return rv; #endif } @@ -833,21 +1460,34 @@ CloseHandle((HANDLE)obj); return 0; #else + struct stat finfo; socklen_t sa_size; struct sockaddr_un sa; - if (obj == 0) + MDBGLOG("net","INFO\t[%s()]: called (obj = %d)",__func__,(int)obj); + + if (obj < 0) { return 0; } - sa_size = sizeof(sa); - if (getsockname((int)obj, (struct sockaddr*)&sa, &sa_size) < 0) - { - return 1; + + fstat((int)obj, &finfo); + + if (S_ISFIFO(finfo.st_mode)) { + close(obj); + unlink(SELFPIPE_PATH); + return 0; + } + else { + sa_size = sizeof(sa); + if (getsockname((int)obj, (struct sockaddr*)&sa, &sa_size) < 0) + { + return 1; + } + close((int)obj); + unlink(sa.sun_path); + return 0; } - close((int)obj); - unlink(sa.sun_path); - return 0; #endif } @@ -861,8 +1501,8 @@ HANDLE handles[256]; DWORD count; DWORD error; - int j; - int i; + ptrdiff_t j; + ptrdiff_t i; j = 0; count = rcount + wcount; @@ -888,15 +1528,20 @@ fd_set rfds; fd_set wfds; struct timeval time; - struct timeval* ptime; - int i; - int max; - int sck; + struct timeval* ptime = (struct timeval *)NULL; + ptrdiff_t i = 0; + int res = 0; + int max = 0; + tbus sck = 0; + + g_memset(&rfds,0,sizeof(fd_set)); + g_memset(&wfds,0,sizeof(fd_set)); + g_memset(&time,0,sizeof(struct timeval)); max = 0; if (mstimeout < 1) { - ptime = 0; + ptime = (struct timeval *)NULL; } else { @@ -909,23 +1554,27 @@ for (i = 0; i < rcount; i++) { sck = (int)(read_objs[i]); - FD_SET(sck, &rfds); - if (sck > max) - { - max = sck; + if (sck > 0) { + FD_SET(sck, &rfds); + if (sck > max) + { + max = sck; + } } } for (i = 0; i < wcount; i++) { sck = (int)(write_objs[i]); - FD_SET(sck, &wfds); - if (sck > max) - { - max = sck; + if (sck > 0) { + FD_SET(sck, &wfds); + if (sck > max) + { + max = sck; + } } } - i = select(max + 1, &rfds, &wfds, 0, ptime); - if (i < 0) + res = select(max + 1, &rfds, &wfds, 0, ptime); + if (res < 0) { /* these are not really errors */ if ((errno == EAGAIN) || @@ -943,7 +1592,7 @@ /*****************************************************************************/ void APP_CC -g_random(char* data, int len) +g_random(char * data, int len) { #if defined(_WIN32) int index; @@ -982,7 +1631,7 @@ /*****************************************************************************/ int APP_CC -g_memcmp(const void* s1, const void* s2, int len) +g_memcmp(const void* s1, const void* s2, size_t len) { return memcmp(s1, s2, len); } @@ -990,7 +1639,7 @@ /*****************************************************************************/ /* returns -1 on error, else return handle or file descriptor */ int APP_CC -g_file_open(const char* file_name) +g_file_open(const char * file_name) { #if defined(_WIN32) return (int)CreateFileA(file_name, GENERIC_READ | GENERIC_WRITE, @@ -1006,13 +1655,123 @@ rv = open(file_name, O_RDONLY); } return rv; -#endif +#endif +} + +/*****************************************************************************/ +/* returns -1 on error, else return handle or file descriptor */ +int APP_CC +g_file_open_flags(const char * file_name, int oflag, mode_t omode) { + int rv = 0; + if (file_name == NULL || g_strlen(file_name) < 1) { + rv = -1; + } + else { +#if defined(_WIN32) + rv = (int)CreateFileA(file_name, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); +#else + rv = open(file_name, oflag, omode); +#endif + } + return rv; +} + +/*****************************************************************************/ +void * APP_CC +g_mmap(void * addr, size_t len, int prot, int flags, int fd, off_t offset) { +#if defined(_WIN32) + return (void *)NULL; +#else + return (len > 0) ? (void *)mmap(addr, len, prot, flags, fd, offset) : (void *)NULL; +#endif +} + +/*****************************************************************************/ +void * APP_CC +g_shmalloc(size_t len) { +#if defined(_WIN32) + return (void *)NULL; +#else + void * rv = (void *)NULL; + rv = g_mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); + if (rv == NULL) { + int fd = 0; + const int oflag = O_RDWR | O_CREAT; + const mode_t omode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + fd = g_file_open_flags("/dev/zero", oflag, omode); + if (fd > 0) { + rv = g_mmap((void *)NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + g_file_close(fd); + } + } + return rv; +#endif +} + +/*****************************************************************************/ +int APP_CC +g_shfree(void * addr, size_t len) { + if (addr != NULL && len > 0) { + return munmap(addr, len); + } + else { + return -1; + } +} + +/*****************************************************************************/ +/* returns -1 on error, else return handle or file descriptor */ +int APP_CC +g_fifo_open(const char * file_name) +{ + int rv = -1; + char * fpath = (char *)NULL; + if (file_name == NULL || g_strlen(file_name) < 1) { + rv = -1; + } + else { + fpath = (char *)g_malloc(sizeof(char) * 512,1); +#if defined(_WIN32) + g_snprintf(fpath,511,"\\\\.\\pipe\\%s",file_name); + rv = (int)CreateNamedPipeA(fpath, + (PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE), + (PIPE_TYPE_BYTE | PIPE_NOWAIT), + 1, /* nMaxInstances */ + 1024, /* nOutBufferSize */ + 1024, /* nInBufferSize */ + 0, /* nDefaultTimeOut (milliseconds) */ + NULL /* lpSecurityAttributes */ + ); +#else + g_snprintf(fpath,511,"%s",file_name); + /* The following statement works correctly under Linux, + * but its behavior is non-standard (the POSIX standard + * does not define what occurs when a FIFO is opened + * with the O_RDWR flag). + */ +// rv = open(fpath, O_RDWR | O_NONBLOCK); + rv = open(fpath, O_RDWR); + + /* If the non-standard method does not work, then the + * following method is more POSIX-compliant; however, it + * may be susceptible to a potential race condition. + */ + if (rv < 0) { + rv = open(fpath, O_RDONLY | O_NONBLOCK); + rv = open(fpath, O_WRONLY | O_NONBLOCK); + } +#endif + } + MDBGLOG("net","INFO\t[%s()]: called (file_name = \"%s\", rv = %d)",__func__,((file_name == NULL || g_strlen(file_name) < 1) ? "(none)" : file_name),rv); + return rv; } /*****************************************************************************/ /* returns error, always 0 */ int APP_CC -g_file_close(int fd) +g_file_close(tbus fd) { #if defined(_WIN32) CloseHandle((HANDLE)fd); @@ -1024,8 +1783,8 @@ /*****************************************************************************/ /* read from file, returns the number of bytes read or -1 on error */ -int APP_CC -g_file_read(int fd, char* ptr, int len) +ptrdiff_t APP_CC +g_file_read(tbus fd, char * ptr, size_t len) { #if defined(_WIN32) if (ReadFile((HANDLE)fd, (LPVOID)ptr, (DWORD)len, (LPDWORD)&len, 0)) @@ -1034,7 +1793,7 @@ } else { - return -1; + return 0; } #else return read(fd, ptr, len); @@ -1043,8 +1802,8 @@ /*****************************************************************************/ /* write to file, returns the number of bytes writen or -1 on error */ -int APP_CC -g_file_write(int fd, char* ptr, int len) +ptrdiff_t APP_CC +g_file_write(tbus fd, const char * ptr, size_t len) { #if defined(_WIN32) if (WriteFile((HANDLE)fd, (LPVOID)ptr, (DWORD)len, (LPDWORD)&len, 0)) @@ -1053,7 +1812,7 @@ } else { - return -1; + return 0; } #else return write(fd, ptr, len); @@ -1063,7 +1822,7 @@ /*****************************************************************************/ /* move file pointer, returns offset on success, -1 on failure */ int APP_CC -g_file_seek(int fd, int offset) +g_file_seek(tbus fd, off_t offset) { #if defined(_WIN32) int rv; @@ -1086,7 +1845,7 @@ /* do a write lock on a file */ /* return boolean */ int APP_CC -g_file_lock(int fd, int start, int len) +g_file_lock(tbus fd, off_t start, size_t len) { #if defined(_WIN32) return LockFile((HANDLE)fd, start, 0, len, 0); @@ -1106,9 +1865,30 @@ } /*****************************************************************************/ +int APP_CC +g_dir_create(const char * dirname, int flags) +{ + int rv = 0; + + if (g_strlen(dirname) > 0) { + if (!g_directory_exist(dirname)) { + rv = mkdir(dirname, flags); + } + else { + rv = -1; + } + } + else { + rv = -1; + } + + return rv; +} + +/*****************************************************************************/ /* returns error */ int APP_CC -g_chmod_hex(const char* filename, int flags) +g_chmod_hex(const char * filename, int flags) { #if defined(_WIN32) return 0; @@ -1135,7 +1915,7 @@ /*****************************************************************************/ /* returns error, always zero */ int APP_CC -g_mkdir(const char* dirname) +g_mkdir(const char * dirname) { #if defined(_WIN32) return 0; @@ -1149,8 +1929,8 @@ /* gets the current working directory and puts up to maxlen chars in dirname always returns 0 */ -char* APP_CC -g_get_current_dir(char* dirname, int maxlen) +char * APP_CC +g_get_current_dir(char * dirname, size_t maxlen) { #if defined(_WIN32) GetCurrentDirectoryA(maxlen, dirname); @@ -1166,7 +1946,7 @@ /*****************************************************************************/ /* returns error, zero on success and -1 on failure */ int APP_CC -g_set_current_dir(char* dirname) +g_set_current_dir(const char * dirname) { #if defined(_WIN32) if (SetCurrentDirectoryA(dirname)) @@ -1185,7 +1965,7 @@ /*****************************************************************************/ /* returns boolean, non zero if the file exists */ int APP_CC -g_file_exist(const char* filename) +g_file_exist(const char * filename) { #if defined(_WIN32) return 0; // use FileAge(filename) <> -1 @@ -1197,7 +1977,7 @@ /*****************************************************************************/ /* returns boolean, non zero if the directory exists */ int APP_CC -g_directory_exist(const char* dirname) +g_directory_exist(const char * dirname) { #if defined(_WIN32) return 0; // use GetFileAttributes and check return value @@ -1219,7 +1999,7 @@ /*****************************************************************************/ /* returns boolean */ int APP_CC -g_create_dir(const char* dirname) +g_create_dir(const char * dirname) { #if defined(_WIN32) return CreateDirectoryA(dirname, 0); // test this @@ -1231,7 +2011,7 @@ /*****************************************************************************/ /* returns boolean */ int APP_CC -g_remove_dir(const char* dirname) +g_remove_dir(const char * dirname) { #if defined(_WIN32) return RemoveDirectoryA(dirname); // test this @@ -1243,7 +2023,7 @@ /*****************************************************************************/ /* returns non zero if the file was deleted */ int APP_CC -g_file_delete(const char* filename) +g_file_delete(const char * filename) { #if defined(_WIN32) return DeleteFileA(filename); @@ -1254,8 +2034,8 @@ /*****************************************************************************/ /* returns file size, -1 on error */ -int APP_CC -g_file_get_size(const char* filename) +size_t APP_CC +g_file_get_size(const char * filename) { #if defined(_WIN32) return -1; @@ -1275,10 +2055,10 @@ /*****************************************************************************/ /* returns length of text */ -int APP_CC -g_strlen(const char* text) +size_t APP_CC +g_strlen(const char * text) { - if (text == 0) + if (text == NULL) { return 0; } @@ -1286,9 +2066,60 @@ } /*****************************************************************************/ +/* returns length of text, up to a maximum value */ +size_t APP_CC +g_strnlen(const char * text, size_t maxlen) +{ + int rv = 0; + if (text == NULL || maxlen < 1) { + rv = 0; + } + else { + rv = strlen(text); + if (rv > maxlen) { + rv = maxlen; + } + } + return rv; +} + +/*****************************************************************************/ +char * APP_CC +g_strstr(const char * s1, const char * s2) +{ + char * rv = (char *)NULL; + if ((s1 != NULL) && (s2 != NULL)) { + rv = strstr(s1,s2); + } + return rv; +} + +/*****************************************************************************/ +char * APP_CC +g_strchr(const char * s, int c) +{ + char * rv = (char *)NULL; + if (s != NULL) { + rv = strchr(s,c); + } + return rv; +} + +/*****************************************************************************/ +char * APP_CC +g_strrchr(const char * s, int c) +{ + char * rv = (char *)NULL; + if (s != NULL) { + rv = strrchr(s,c); + } + return rv; +} + +/*****************************************************************************/ /* returns dest */ -char* APP_CC -g_strcpy(char* dest, const char* src) +char * APP_CC +g_strcpy(char * dest, const char * src) { if (src == 0 && dest != 0) { @@ -1304,10 +2135,10 @@ /*****************************************************************************/ /* returns dest */ -char* APP_CC -g_strncpy(char* dest, const char* src, int len) +char * APP_CC +g_strncpy(char * dest, const char * src, size_t len) { - char* rv; + char * rv; if (src == 0 && dest != 0) { @@ -1325,8 +2156,8 @@ /*****************************************************************************/ /* returns dest */ -char* APP_CC -g_strcat(char* dest, const char* src) +char * APP_CC +g_strcat(char * dest, const char * src) { if (dest == 0 || src == 0) { @@ -1336,40 +2167,89 @@ } /*****************************************************************************/ +/* returns dest */ +char * APP_CC +g_strncat(char * dest, const char * src, size_t lmt) +{ + if (dest == 0 || src == 0) + { + return dest; + } + return strncat(dest, src, lmt); +} + +/*****************************************************************************/ /* if in = 0, return 0 else return newly alloced copy of in */ -char* APP_CC -g_strdup(const char* in) +char * APP_CC +g_strdup(const char * in) { int len; - char* p; + char * p; if (in == 0) { return 0; } len = g_strlen(in); - p = (char*)g_malloc(len + 1, 0); - g_strcpy(p, in); + p = (char *)g_malloc(len + 1, 0); + if (p != NULL) { + g_strcpy(p, in); + } + return p; +} + +/*****************************************************************************/ +char * APP_CC +g_strndup(const char * in, size_t size) { + int len = 0; + char * p = (char *)NULL; + +#if !defined(MINVAL) +#define MINVAL(x,y) (((x) > (y)) ? (y) : (x)) +#define __NOMINVAL +#endif + + if (in == NULL) { + return 0; + } + len = MINVAL(g_strlen(in),size); + p = (char *)g_malloc((len + 1), 1); + if (p != NULL) { + g_strncpy(p, in, len); + } return p; + +#if defined(__NOMINVAL) +#undef MINVAL +#endif +} + + +/*****************************************************************************/ +#define m_strdup_printf(fmtstr, ...) { \ + char p[1024]; \ + g_memset(p,0,1024); \ + g_snprintf(p,1023,fmtstr, __VA_ARGS__); \ + return p; \ } /*****************************************************************************/ int APP_CC -g_strcmp(const char* c1, const char* c2) +g_strcmp(const char * c1, const char * c2) { return strcmp(c1, c2); } /*****************************************************************************/ int APP_CC -g_strncmp(const char* c1, const char* c2, int len) +g_strncmp(const char * c1, const char * c2, size_t len) { return strncmp(c1, c2, len); } /*****************************************************************************/ int APP_CC -g_strcasecmp(const char* c1, const char* c2) +g_strcasecmp(const char * c1, const char * c2) { #if defined(_WIN32) return stricmp(c1, c2); @@ -1380,7 +2260,7 @@ /*****************************************************************************/ int APP_CC -g_strncasecmp(const char* c1, const char* c2, int len) +g_strncasecmp(const char * c1, const char * c2, size_t len) { #if defined(_WIN32) return strnicmp(c1, c2, len); @@ -1391,7 +2271,7 @@ /*****************************************************************************/ int APP_CC -g_atoi(char* str) +g_atoi(char * str) { if (str == 0) { @@ -1402,16 +2282,16 @@ /*****************************************************************************/ int APP_CC -g_htoi(char* str) +g_htoi(char * str) { - int len; - int index; + size_t len; + ptrdiff_t index; int rv; int val; int shift; rv = 0; - len = strlen(str); + len = g_strlen(str); index = len - 1; shift = 0; while (index >= 0) @@ -1480,9 +2360,9 @@ /*****************************************************************************/ int APP_CC -g_pos(char* str, const char* to_find) +g_pos(char * str, const char * to_find) { - char* pp; + char * pp; pp = strstr(str, to_find); if (pp == 0) @@ -1494,7 +2374,7 @@ /*****************************************************************************/ int APP_CC -g_mbstowcs(twchar* dest, const char* src, int n) +g_mbstowcs(twchar * dest, const char * src, int n) { wchar_t* ldest; int rv; @@ -1506,7 +2386,7 @@ /*****************************************************************************/ int APP_CC -g_wcstombs(char* dest, const twchar* src, int n) +g_wcstombs(char * dest, const twchar * src, int n) { const wchar_t* lsrc; int rv; @@ -1522,14 +2402,14 @@ /* trim_flags 1 trim left, 2 trim right, 3 trim both, 4 trim through */ /* this will always shorten the string or not change it */ int APP_CC -g_strtrim(char* str, int trim_flags) +g_strtrim(char * str, int trim_flags) { - int index; - int len; - int text1_index; - int got_char; - wchar_t* text; - wchar_t* text1; + ptrdiff_t index = 0; + size_t len = 0; + ptrdiff_t text1_index = 0; + int got_char = 0; + wchar_t * text = (wchar_t *)NULL; + wchar_t * text1 = (wchar_t *)NULL; len = mbstowcs(0, str, 0); if (len < 1) @@ -1637,7 +2517,7 @@ /*****************************************************************************/ long APP_CC -g_load_library(char* in) +g_load_library(char * in) { #if defined(_WIN32) return (long)LoadLibraryA(in); @@ -1664,7 +2544,7 @@ /*****************************************************************************/ /* returns NULL if not found */ void* APP_CC -g_get_proc_address(long lib, const char* name) +g_get_proc_address(long lib, const char * name) { if (lib == 0) { @@ -1680,7 +2560,7 @@ /*****************************************************************************/ /* does not work in win32 */ int APP_CC -g_system(char* aexec) +g_system(char * aexec) { #if defined(_WIN32) return 0; @@ -1691,7 +2571,7 @@ /*****************************************************************************/ /* does not work in win32 */ -char* APP_CC +char * APP_CC g_get_strerror(void) { #if defined(_WIN32) @@ -1715,7 +2595,7 @@ /*****************************************************************************/ /* does not work in win32 */ int APP_CC -g_execvp(const char* p1, char* args[]) +g_execvp(const char * p1, char * args[]) { #if defined(_WIN32) return 0; @@ -1727,7 +2607,7 @@ /*****************************************************************************/ /* does not work in win32 */ int APP_CC -g_execlp3(const char* a1, const char* a2, const char* a3) +g_execlp3(const char * a1, const char * a2, const char * a3) { #if defined(_WIN32) return 0; @@ -1830,7 +2710,7 @@ /* returns error, zero is success, non zero is error */ /* does not work in win32 */ int APP_CC -g_initgroups(const char* user, int gid) +g_initgroups(const char * user, int gid) { #if defined(_WIN32) return 0; @@ -1898,14 +2778,18 @@ #if defined(_WIN32) return 0; #else - int rv; - - rv = waitpid(pid, 0, 0); - if (rv == -1) - { - if (errno == EINTR) /* signal occurred */ + int rv = 0; + if (pid < 0) { + rv = -1; + } + else { + rv = waitpid(pid, 0, 0); + if (rv == -1) { - rv = 0; + if (errno == EINTR) /* signal occurred */ + { + rv = 0; + } } } return rv; @@ -1926,7 +2810,7 @@ /*****************************************************************************/ /* does not work in win32 */ int APP_CC -g_setenv(const char* name, const char* value, int rewrite) +g_setenv(const char * name, const char * value, int rewrite) { #if defined(_WIN32) return 0; @@ -1937,8 +2821,8 @@ /*****************************************************************************/ /* does not work in win32 */ -char* APP_CC -g_getenv(const char* name) +char * APP_CC +g_getenv(const char * name) { #if defined(_WIN32) return 0; @@ -1967,6 +2851,21 @@ } /*****************************************************************************/ +int APP_CC +g_gettid(void) +{ +#if defined(_WIN32) + return (int)GetCurrentThreadId(); +#else +#if defined(__linux__) + return syscall(SYS_gettid); +#else + return (int)pthread_self(); +#endif +#endif +} + +/*****************************************************************************/ /* does not work in win32 */ int APP_CC g_sigterm(int pid) @@ -1982,8 +2881,8 @@ /* returns 0 if ok */ /* does not work in win32 */ int APP_CC -g_getuser_info(const char* username, int* gid, int* uid, char* shell, - char* dir, char* gecos) +g_getuser_info(const char * username, int* gid, int* uid, char * shell, + char * dir, char * gecos) { #if defined(_WIN32) return 1; @@ -2023,7 +2922,7 @@ /* returns 0 if ok */ /* does not work in win32 */ int APP_CC -g_getgroup_info(const char* groupname, int* gid) +g_getgroup_info(const char * groupname, int* gid) { #if defined(_WIN32) return 1; @@ -2048,13 +2947,13 @@ /* if zero is returned, then ok is set */ /* does not work in win32 */ int APP_CC -g_check_user_in_group(const char* username, int gid, int* ok) +g_check_user_in_group(const char * username, int gid, int* ok) { #if defined(_WIN32) return 1; #else - struct group* groups; - int i; + struct group * groups = (struct group *)NULL; + ptrdiff_t i = 0; groups = getgrgid(gid); if (groups == 0) @@ -2082,6 +2981,21 @@ for windows, returns the number of seconds since the machine was started. */ int APP_CC +g_time(time_t * tval) +{ +#if defined(_WIN32) + return GetTickCount() / 1000; +#else + return time(tval); +#endif +} + +/*****************************************************************************/ +/* returns the time since the Epoch (00:00:00 UTC, January 1, 1970), + measured in seconds. + for windows, returns the number of seconds since the machine was + started. */ +int APP_CC g_time1(void) { #if defined(_WIN32) @@ -2094,17 +3008,17 @@ /*****************************************************************************/ /* returns the number of milliseconds since the machine was started. */ -int APP_CC +long int APP_CC g_time2(void) { #if defined(_WIN32) return (int)GetTickCount(); #else struct tms tm; - clock_t num_ticks; - + clock_t num_ticks = 0; + g_memset(&tm,0,sizeof(struct tms)); num_ticks = times(&tm); - return (int)(num_ticks * 10); + return (long int)(num_ticks * 10); #endif } @@ -2123,3 +3037,346 @@ return (tp.tv_sec * 1000) + (tp.tv_usec / 1000); #endif } + +/*****************************************************************************/ +/* returns list of files in a directory */ +char ** APP_CC +g_dir_list_contents(const char * dirname, char ** contents, int * count) { + DIR * dp = (DIR *)NULL; + struct dirent * ep = (struct dirent *)NULL; + strlist * lst = (strlist *)NULL; + lst = strlist_init(); + if (g_strlen(dirname)>0) { + dp = opendir (dirname); + } + if (dp != NULL) { + while ((ep = readdir(dp)) > 0) { + if (g_strlen(ep->d_name) > 0) { + lst = strlist_append(&lst, ep->d_name); + } + } + (void) closedir (dp); + } + contents = strlist_to_array(lst,count); + return contents; +} + + +/*****************************************************************************/ +/* Subtract the "struct timeval" values X and Y, + that is, subtract Y from X, storing the result in RESULT. + Return 1 if the difference is negative, otherwise 0. */ +int APP_CC +timeval_subtract (result, x, y) struct timeval *result, *x, *y; +{ + /* Perform the carry for the later subtraction by updating y. */ + if (x->tv_usec < y->tv_usec) { + int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; + y->tv_usec -= 1000000 * nsec; + y->tv_sec += nsec; + } + if (x->tv_usec - y->tv_usec > 1000000) { + int nsec = (x->tv_usec - y->tv_usec) / 1000000; + y->tv_usec += 1000000 * nsec; + y->tv_sec -= nsec; + } + + /* Compute the time remaining to wait. + tv_usec is certainly positive. */ + result->tv_sec = x->tv_sec - y->tv_sec; + result->tv_usec = x->tv_usec - y->tv_usec; + + /* Return 1 if result is negative. */ + return x->tv_sec < y->tv_sec; +} + +#define ONE_MILLION 1000000 + +/** + * Make a timeval value. + * + * @param sec the number of seconds. + * @param usec the number of microseconds. + * @return the timeval value of @ref sec and @ref usec. + */ +inline struct timeval +mk_timeval(int sec, int usec) +{ + struct timeval t; + t.tv_sec = sec; + t.tv_usec = usec; + return t; +} + +/** + * Adjust the timeval value so it is valid. + * + * A timeval value is valid if the number of microseconds is not negative, + * and is smaller than 1000000 (i.e., one million). + * + * @param t the timeval value to adjust. + * @return the adjusted timeval value. Note that the original @ref t value + * is also adjusted. + */ +inline struct timeval * +timeval_round(struct timeval * t) +{ + if (t->tv_usec < 0) { + t->tv_usec += ONE_MILLION ; + t->tv_sec -- ; + } else if (t->tv_usec >= ONE_MILLION) { + t->tv_usec -= ONE_MILLION ; + t->tv_sec ++ ; + } + return t; +} + +/** + * Convert a timeval value to a double-float value. + * + * @param t the timeval value to convert to a double-float value. + * @return the double-float value of @ref t. + */ +inline double +timeval_to_double(const struct timeval * t) +{ + return t->tv_sec * 1.0 + t->tv_usec * 1.0e-6; +} + +/** + * Convert a double-float value to a timeval value. + * + * @param d the double-float value to convert to a timeval value. + * @return the timeval value of @ref. + */ +inline struct timeval +double_to_timeval(const double * d) +{ + double tmp = 0.; + struct timeval t; + t.tv_sec = (int)*d; + tmp = *d - (double)t.tv_sec; + t.tv_usec = (int)(tmp * ONE_MILLION); + return t; +} + + +/*** iconv functions: ***/ + +int APP_CC +g_iconv_init() { + int rv = 0; + const char platform_encoding[] = "UTF-8"; + const char rdp_encoding[] = "UTF-16LE"; + + pthread_mutex_init(&g_mutex_iconv,NULL); + + pthread_mutex_lock(&g_mutex_iconv); + if (g_icd == (iconv_t)(-1)) { + g_icd = iconv_open(platform_encoding,rdp_encoding); + } + if (g_ocd == (iconv_t)(-1)) { + g_ocd = iconv_open(rdp_encoding,platform_encoding); + } + pthread_mutex_unlock(&g_mutex_iconv); + + return rv; +} + +int APP_CC +g_iconv_end() { + int rv = 0; + + pthread_mutex_lock(&g_mutex_iconv); + if (g_icd > (iconv_t)(-1)) { + iconv_close(g_icd); + g_icd = (iconv_t)(-1); + } + if (g_ocd > (iconv_t)(-1)) { + iconv_close(g_ocd); + g_ocd = (iconv_t)(-1); + } + pthread_mutex_unlock(&g_mutex_iconv); + + pthread_mutex_destroy(&g_mutex_iconv); + + return rv; +} + +int APP_CC +g_instr(char ** ostr, int * olen, char ** istr, int * ilen) { + int rv = 0; + + pthread_mutex_lock(&g_mutex_iconv); + iconv(g_icd, istr, (size_t *)ilen, ostr, (size_t *)olen); + + *ostr = '\0'; + pthread_mutex_unlock(&g_mutex_iconv); + + return rv; +} + +int APP_CC +g_outstr(char ** ostr, int * olen, char ** istr, int * ilen) { + int rv = 0; + + pthread_mutex_lock(&g_mutex_iconv); + iconv(g_ocd, istr, (size_t *)ilen, ostr, (size_t *)olen); + *ostr = '\0'; + pthread_mutex_unlock(&g_mutex_iconv); + + return rv; +} + +/**** ****/ +/**** Timestamp conversion ****/ +/**** ****/ + +/* Convert a UNIX time_t into a Windows filetime_t */ +filetime_t UnixToFileTime(time_t utime) { + int64_t tconv = ((int64_t)utime * RATE_DIFF) + EPOCH_DIFF; + return tconv; +} + +/* Convert a Windows filetime_t into a UNIX time_t */ +time_t FileTimeToUnix(filetime_t ftime) { + int64_t tconv = (ftime - EPOCH_DIFF) / RATE_DIFF; + return (time_t)tconv; +} + +/* g_strsep() */ +char * g_strsep(char ** stringp, const char * delim) { + char * rv = (char *)NULL; + + if (stringp != NULL && *stringp != NULL && delim != NULL && g_strlen(delim) > 0) { + rv = strsep(stringp, delim); + } + + return rv; +} + +/*****************************************************************************/ +int APP_CC +g_mkfifo(const char * iname, mode_t imode) { + int rv = 0; + char * fname = (char *)NULL; + mode_t fmode = 0; + + if (iname == NULL || g_strlen(iname) < 1) { + rv = -1; + } + else { + fmode = imode; + fname = g_strdup(iname); + rv = mkfifo(fname, fmode); + } + + return rv; +} + +/*****************************************************************************/ +int APP_CC +g_mknod(const char * iname, mode_t imode, dev_t idev) { + int rv = 0; + char * fname = (char *)NULL; + mode_t fmode = 0; + dev_t fdev = 0; + + if (iname == NULL || g_strlen(iname) < 1) { + rv = -1; + } + else { + fmode = imode; + fdev = idev; + fname = g_strdup(iname); + rv = mknod(fname, fmode, fdev); + } + + return rv; +} + +#if defined(XRDP_ENABLE_NETLINK) + +/*****************************************************************************/ +int APP_CC +g_netlink_socket(void) { + DBGLOG("net","[os_calls]->g_netlink_socket() called"); +#if defined(_WIN32) + return 0; +#else + return socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); +#endif +} + +/*****************************************************************************/ +void APP_CC +g_netlink_close(tbus sck) { + DBGLOG("net","[os_calls]->g_netlink_close() called"); + if (sck != 0) + { +#if defined(_WIN32) +#else + close(sck); +#endif + } + DBGLOG("net","[os_calls]->g_netlink_close() done."); +} + +/*****************************************************************************/ +int APP_CC +g_netlink_bind(tbus sck) { +#if defined(_WIN32) + return -1; +#else + struct sockaddr_nl s; + //MDBGLOG("net","[os_calls]->g_netlink_bind() called: sck = %d; port = %s\0",sck,port); + g_memset(&s, 0, sizeof(struct sockaddr_nl)); + s.nl_family = AF_NETLINK; + s.nl_groups = -1; + s.nl_pid = 0; + return bind(sck, (struct sockaddr *)&s, sizeof(struct sockaddr_nl)); +#endif +} + +#endif + +/*****************************************************************************/ +/* produce a hex dump */ +void APP_CC +g_hexdump_file(const char * f, char * p, size_t len) { + + unsigned char * line = (unsigned char *)NULL; + ptrdiff_t i = 0; + int thisline = 0; + ptrdiff_t offset = 0; + FILE * fp = (FILE *)NULL; + + fp = fopen(f,"a"); + line = (unsigned char *)p; + offset = 0; + while (offset < len) + { + fprintf(fp, "%04x \t", offset); + thisline = len - offset; + if (thisline > 16) + { + thisline = 16; + } + for (i = 0; i < thisline; i++) + { + fprintf(fp,"%02x ", line[i]); + } + for (; i < 16; i++) + { + fprintf(fp," "); + } + for (i = 0; i < thisline; i++) + { + fprintf(fp,"%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.'); + } + fprintf(fp, "\n"); + offset += thisline; + line += thisline; + } + fclose(fp); +} diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/os_calls.h posixrdp/posixxrdp.orig/common/os_calls.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/os_calls.h 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/os_calls.h 2010-11-08 09:56:43.000000000 +0100 @@ -25,177 +25,268 @@ #if !defined(OS_CALLS_H) #define OS_CALLS_H +#include +#include +#include +#include +#include +#include +#include +#include #include "arch.h" + /* + * Define this constant (_XRDP_ENABLE_IPv6_) to + * compile with IPv6 support: + */ +#define _XRDP_ENABLE_IPv6_ + +#define CHANSRV_USERNAME_PATH "/tmp/xrdp_chansrv_%8.8x_username" +#ifndef SELFPIPE_PATH +#define SELFPIPE_PATH "/tmp/xrdp_chansrv_%8.8x_selfpipe" +#endif +#ifndef AUDIO_FIFO_PATH +#define AUDIO_FIFO_PATH "/tmp/xrdp_audio_%d_fifo" +#endif + +#ifndef NETLINK_CONNECTOR +#define NETLINK_CONNECTOR 11 +#endif + void APP_CC g_init(void); void APP_CC g_deinit(void); void* APP_CC -g_malloc(int size, int zero); +g_malloc(int, int); +void * APP_CC +g_realloc(void *, int); void APP_CC -g_free(void* ptr); +g_free(void *); +void DEFAULT_CC +g_printf(const char *, ...); void DEFAULT_CC -g_printf(const char *format, ...); +g_sprintf(char *, const char *, ...); void DEFAULT_CC -g_sprintf(char* dest, const char* format, ...); +g_snprintf(char *, size_t, const char *, ...); +int DEFAULT_CC +g_scnprintf(char *, size_t, const char *, ...); void DEFAULT_CC -g_snprintf(char* dest, int len, const char* format, ...); +g_writeln(const char *, ...); void DEFAULT_CC -g_writeln(const char* format, ...); +g_write(const char *, ...); void DEFAULT_CC -g_write(const char* format, ...); +g_writeln_err(const char *, ...); +void DEFAULT_CC +g_write_err(const char *, ...); +void APP_CC +g_hexdump(const char *, size_t); void APP_CC -g_hexdump(char* p, int len); +g_hexdump_file(const char *, char *, size_t); void APP_CC -g_memset(void* ptr, int val, int size); +g_memset(void *, int, size_t); void APP_CC -g_memcpy(void* d_ptr, const void* s_ptr, int size); +g_memcpy(void *, const void *, size_t); int APP_CC g_getchar(void); int APP_CC -g_tcp_set_no_delay(int sck); +g_tcp_set_no_delay(tbus); int APP_CC g_tcp_socket(void); int APP_CC +g_netlink_socket(void); +int APP_CC g_tcp_local_socket(void); +int APP_CC +g_socketpair(int *); void APP_CC -g_tcp_close(int sck); +g_tcp_close(tbus); +void APP_CC +g_netlink_close(tbus); +int APP_CC +g_tcp_connect(tbus, const char *, const char *); +int APP_CC +g_tcp_local_connect(tbus, const char *); int APP_CC -g_tcp_connect(int sck, const char* address, const char* port); +g_tcp_force_send(tbus, const char *, size_t); int APP_CC -g_tcp_local_connect(int sck, const char* port); +g_tcp_force_recv(tbus, const char *, size_t); int APP_CC -g_tcp_force_send(int sck, char* data, int len); +g_tcp_set_non_blocking(tbus); int APP_CC -g_tcp_force_recv(int sck, char* data, int len); +g_tcp_set_blocking(tbus); int APP_CC -g_tcp_set_non_blocking(int sck); +g_fifo_set_blocking(tbus); int APP_CC -g_tcp_bind(int sck, char* port); +g_tcp_bind_flags(tbus, const char *, int); int APP_CC -g_tcp_local_bind(int sck, char* port); +g_tcp_bind(tbus, const char *); int APP_CC -g_tcp_listen(int sck); +g_netlink_bind(tbus); int APP_CC -g_tcp_accept(int sck); +g_tcp_local_bind(tbus, const char *); int APP_CC -g_tcp_recv(int sck, void* ptr, int len, int flags); +g_tcp_listen(tbus); int APP_CC -g_tcp_send(int sck, const void* ptr, int len, int flags); +g_tcp_accept(tbus); +size_t APP_CC +g_tcp_recv(tbus, void *, size_t, int); +size_t APP_CC +g_fifo_read(tbus, void *, size_t); +size_t APP_CC +g_fifo_write(tbus, const void *, size_t); +size_t APP_CC +g_tcp_send(tbus, const void *, size_t, int); +size_t APP_CC +g_tcp_send_force(tbus, const void *, size_t, int); int APP_CC -g_tcp_last_error_would_block(int sck); +g_tcp_last_error_would_block(tbus); int APP_CC -g_tcp_socket_ok(int sck); +g_tcp_socket_ok(tbus); int APP_CC -g_tcp_can_send(int sck, int millis); +g_tcp_can_send(tbus, int); int APP_CC -g_tcp_can_recv(int sck, int millis); +g_tcp_can_recv(tbus, int); int APP_CC -g_tcp_select(int sck1, int sck2); +g_fifo_can_read(tbus, int); +int APP_CC +g_tcp_select(tbus, tbus); +void APP_CC +g_sleep(uint64_t); void APP_CC -g_sleep(int msecs); +g_usleep(uint64_t); +tbus APP_CC +g_create_wait_obj(const char *); +tbus APP_CC +g_create_wait_obj_from_path(const char *); tbus APP_CC -g_create_wait_obj(char* name); +g_create_wait_obj_from_socket(tbus, int); tbus APP_CC -g_create_wait_obj_from_socket(tbus socket, int write); +g_create_wait_obj_from_fifo(tbus, int); void APP_CC -g_delete_wait_obj_from_socket(tbus wait_obj); +g_delete_wait_obj_from_socket(tbus); int APP_CC -g_set_wait_obj(tbus obj); +g_set_wait_obj(tbus); int APP_CC -g_reset_wait_obj(tbus obj); +g_reset_wait_obj(tbus); int APP_CC -g_is_wait_obj_set(tbus obj); +g_is_wait_obj_set(tbus); int APP_CC -g_delete_wait_obj(tbus obj); +g_delete_wait_obj(tbus); int APP_CC -g_obj_wait(tbus* read_objs, int rcount, tbus* write_objs, int wcount, - int mstimeout); +g_obj_wait(tbus *, int, tbus *, int, int); void APP_CC -g_random(char* data, int len); +g_random(char *, int); int APP_CC -g_abs(int i); +g_abs(int); int APP_CC -g_memcmp(const void* s1, const void* s2, int len); +g_memcmp(const void *, const void *, size_t); int APP_CC -g_file_open(const char* file_name); +g_file_open(const char *); int APP_CC -g_file_close(int fd); +g_file_open_flags(const char *, int, mode_t); +void * APP_CC +g_shmalloc(size_t); int APP_CC -g_file_read(int fd, char* ptr, int len); +g_shfree(void *, size_t); +void * APP_CC +g_mmap(void *, size_t, int, int, int, off_t); int APP_CC -g_file_write(int fd, char* ptr, int len); +g_mkfifo(const char *, mode_t); int APP_CC -g_file_seek(int fd, int offset); +g_create_fifo(const char *); int APP_CC -g_file_lock(int fd, int start, int len); +g_fifo_open(const char *); int APP_CC -g_chmod_hex(const char* filename, int flags); +g_file_close(tbus); +ptrdiff_t APP_CC +g_file_read(tbus, char *, size_t); +ptrdiff_t APP_CC +g_file_write(tbus, const char *, size_t); int APP_CC -g_mkdir(const char* dirname); -char* APP_CC -g_get_current_dir(char* dirname, int maxlen); +g_file_seek(tbus, off_t); int APP_CC -g_set_current_dir(char* dirname); +g_file_lock(tbus, off_t, size_t); int APP_CC -g_file_exist(const char* filename); +g_chmod_hex(const char *, int); int APP_CC -g_directory_exist(const char* dirname); +g_mkdir(const char *); +char * APP_CC +g_get_current_dir(char *, size_t); int APP_CC -g_create_dir(const char* dirname); +g_set_current_dir(const char *); int APP_CC -g_remove_dir(const char* dirname); +g_file_exist(const char *); int APP_CC -g_file_delete(const char* filename); +g_directory_exist(const char *); int APP_CC -g_file_get_size(const char* filename); +g_create_dir(const char *); int APP_CC -g_strlen(const char* text); -char* APP_CC -g_strcpy(char* dest, const char* src); -char* APP_CC -g_strncpy(char* dest, const char* src, int len); -char* APP_CC -g_strcat(char* dest, const char* src); -char* APP_CC -g_strdup(const char* in); +g_remove_dir(const char *); int APP_CC -g_strcmp(const char* c1, const char* c2); +g_file_delete(const char *); +size_t APP_CC +g_file_get_size(const char *); +size_t APP_CC +g_strlen(const char *); +size_t APP_CC +g_strnlen(const char *, size_t); +char * APP_CC +g_strstr(const char *, const char *); +char * APP_CC +g_strchr(const char *, int); +char * APP_CC +g_strrchr(const char *, int); +char * APP_CC +g_strcpy(char *, const char *); +char * APP_CC +g_strncpy(char *, const char *, size_t); +char * APP_CC +g_strcat(char *, const char *); +char * APP_CC +g_strncat(char *, const char *, size_t); +char * APP_CC +g_strdup(const char *); +char * APP_CC +g_strndup(const char *, size_t); +/* char * APP_CC +g_strdup_printf (const gchar *format, ...) G_GNUC_PRINTF (1, 2) G_GNUC_MALLOC; */ int APP_CC -g_strncmp(const char* c1, const char* c2, int len); +g_strcmp(const char * c1, const char * c2); int APP_CC -g_strcasecmp(const char* c1, const char* c2); +g_strncmp(const char * c1, const char * c2, size_t len); int APP_CC -g_strncasecmp(const char* c1, const char* c2, int len); +g_strcasecmp(const char * c1, const char * c2); int APP_CC -g_atoi(char* str); +g_strncasecmp(const char * c1, const char * c2, size_t len); int APP_CC -g_htoi(char* str); +g_atoi(char * str); int APP_CC -g_pos(char* str, const char* to_find); +g_htoi(char * str); int APP_CC -g_mbstowcs(twchar* dest, const char* src, int n); +g_pos(char * str, const char * to_find); int APP_CC -g_wcstombs(char* dest, const twchar* src, int n); +g_mbstowcs(twchar * dest, const char * src, int n); int APP_CC -g_strtrim(char* str, int trim_flags); +g_wcstombs(char * dest, const twchar * src, int n); +int APP_CC +g_strtrim(char * str, int trim_flags); long APP_CC -g_load_library(char* in); +g_load_library(char * in); int APP_CC g_free_library(long lib); void* APP_CC -g_get_proc_address(long lib, const char* name); +g_get_proc_address(long lib, const char * name); int APP_CC -g_system(char* aexec); -char* APP_CC +g_system(char * aexec); +char * APP_CC g_get_strerror(void); int APP_CC g_get_errno(void); int APP_CC -g_execvp(const char* p1, char* args[]); +g_execvp(const char * p1, char * args[]); int APP_CC -g_execlp3(const char* a1, const char* a2, const char* a3); +g_execlp3(const char * a1, const char * a2, const char * a3); void APP_CC g_signal_child_stop(void (*func)(int)); void APP_CC @@ -213,7 +304,7 @@ int APP_CC g_setgid(int pid); int APP_CC -g_initgroups(const char* user, int gid); +g_initgroups(const char * user, int gid); int APP_CC g_getuid(void); int APP_CC @@ -225,27 +316,59 @@ void APP_CC g_clearenv(void); int APP_CC -g_setenv(const char* name, const char* value, int rewrite); -char* APP_CC -g_getenv(const char* name); +g_setenv(const char * name, const char * value, int rewrite); +char * APP_CC +g_getenv(const char * name); int APP_CC g_exit(int exit_code); int APP_CC g_getpid(void); int APP_CC +g_gettid(void); +int APP_CC g_sigterm(int pid); int APP_CC -g_getuser_info(const char* username, int* gid, int* uid, char* shell, - char* dir, char* gecos); +g_getuser_info(const char * username, int* gid, int* uid, char * shell, + char * dir, char * gecos); int APP_CC -g_getgroup_info(const char* groupname, int* gid); +g_getgroup_info(const char * groupname, int* gid); int APP_CC -g_check_user_in_group(const char* username, int gid, int* ok); +g_check_user_in_group(const char * username, int gid, int* ok); int APP_CC -g_time1(void); +g_time(time_t *); int APP_CC +g_time1(void); +long int APP_CC g_time2(void); int APP_CC g_time3(void); +char ** APP_CC +g_dir_list_contents(const char * dirname, char ** contents, int * count); +int APP_CC +g_dir_create(const char * dirname, int flags); +int APP_CC +timeval_subtract (struct timeval *, struct timeval *, struct timeval *); +struct timeval APP_CC +mk_timeval(int, int); +struct timeval * APP_CC +timeval_round(struct timeval *); +double APP_CC +timeval_to_double(const struct timeval *); +struct timeval APP_CC +double_to_timeval(const double *); + +/* string encoding conversion functions: */ +int APP_CC g_iconv_init(); +int APP_CC g_iconv_end(); +int APP_CC g_instr(char **, int *, char **, int *); +int APP_CC g_outstr(char **, int *, char **, int *); + +char * APP_CC g_strsep(char **, const char *); + +#define EPOCH_DIFF 0x019DB1DED53E8000LL /* 116444736000000000 nsecs */ +#define RATE_DIFF 10000000 /* 100 nsecs */ +typedef int64_t filetime_t; +filetime_t UnixToFileTime(time_t); +time_t FileTimeToUnix(filetime_t); #endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/parse.h posixrdp/posixxrdp.orig/common/parse.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/parse.h 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/parse.h 2010-11-08 09:56:43.000000000 +0100 @@ -29,6 +29,7 @@ #if !defined(PARSE_H) #define PARSE_H +#include #include "arch.h" #if defined(L_ENDIAN) @@ -37,6 +38,8 @@ #error Unknown endianness. #endif +#define NEED_ALIGN + /* parser state */ struct stream { @@ -112,6 +115,19 @@ } /******************************************************************************/ +#define s_get_pos(s) \ + ((void *)((s)->p)) + +/******************************************************************************/ +#define s_size(s) (size_t)((s)->end - (s)->data) + +/******************************************************************************/ +#define s_current_size(s) (size_t)((s)->p - (s)->data) + +/******************************************************************************/ +#define s_crc32(s) (uint32_t)(((s)->data != NULL && (s)->end != NULL && (s)->end > (s)->data) ? Crc32_ComputeBuf(0, (s)->data, s_size(s)) : 0) + +/******************************************************************************/ #define in_sint8(s, v) \ { \ (v) = *((signed char*)((s)->p)); \ @@ -211,6 +227,107 @@ } /******************************************************************************/ +#if defined(B_ENDIAN) || defined(NEED_ALIGN) +#define in_int32_le(s, v) \ +{ \ + (v) = (int) \ + ( \ + (*((unsigned char*)((s)->p + 0)) << 0) | \ + (*((unsigned char*)((s)->p + 1)) << 8) | \ + (*((unsigned char*)((s)->p + 2)) << 16) | \ + (*((unsigned char*)((s)->p + 3)) << 24) \ + ); \ + (s)->p += 4; \ +} +#else +#define in_int32_le(s, v) \ +{ \ + (v) = *((int*)((s)->p)); \ + (s)->p += 4; \ +} +#endif + +#define in_sint32_le(s, v) in_int32_le(s, v) + +/******************************************************************************/ +#if defined(B_ENDIAN) || defined(NEED_ALIGN) +#define in_uint64_le(s, v) \ +{ \ + (v) = (unsigned long long) \ + ( \ + (*((unsigned char*)((s)->p + 0)) << 0) | \ + (*((unsigned char*)((s)->p + 1)) << 8) | \ + (*((unsigned char*)((s)->p + 2)) << 16) | \ + (*((unsigned char*)((s)->p + 3)) << 24) | \ + ((unsigned long long)(*((unsigned char*)((s)->p + 4))) << 32) | \ + ((unsigned long long)(*((unsigned char*)((s)->p + 5))) << 40) | \ + ((unsigned long long)(*((unsigned char*)((s)->p + 6))) << 48) | \ + ((unsigned long long)(*((unsigned char*)((s)->p + 7))) << 56) \ + ); \ + (s)->p += 8; \ +} +#else +#define in_uint64_le(s, v) \ +{ \ + (v) = *((unsigned long long*)((s)->p)); \ + (s)->p += 8; \ +} +#endif + +/******************************************************************************/ +#if defined(B_ENDIAN) || defined(NEED_ALIGN) +#define in_int64_le(s, v) \ +{ \ + (v) = (unsigned long long) \ + ( \ + (*((unsigned char*)((s)->p + 0)) << 0) | \ + (*((unsigned char*)((s)->p + 1)) << 8) | \ + (*((unsigned char*)((s)->p + 2)) << 16) | \ + (*((unsigned char*)((s)->p + 3)) << 24) | \ + ((unsigned long long)(*((unsigned char*)((s)->p + 4))) << 32) | \ + ((unsigned long long)(*((unsigned char*)((s)->p + 5))) << 40) | \ + ((unsigned long long)(*((unsigned char*)((s)->p + 6))) << 48) | \ + ((unsigned long long)(*((unsigned char*)((s)->p + 7))) << 56) \ + ); \ + (s)->p += 8; \ +} +#else +#define in_int64_le(s, v) \ +{ \ + (v) = *((unsigned long long*)((s)->p)); \ + (s)->p += 8; \ +} +#endif + +/******************************************************************************/ +#define in_uint64_be(s, v) \ +{ \ + (v) = *((unsigned char*)((s)->p)); \ + (s)->p++; \ + (v) <<= 8; \ + (v) |= *((unsigned char*)((s)->p)); \ + (s)->p++; \ + (v) <<= 8; \ + (v) |= *((unsigned char*)((s)->p)); \ + (s)->p++; \ + (v) <<= 8; \ + (v) |= *((unsigned char*)((s)->p)); \ + (s)->p++; \ + (v) <<= 8; \ + (v) |= *((unsigned char*)((s)->p)); \ + (s)->p++; \ + (v) <<= 8; \ + (v) |= *((unsigned char*)((s)->p)); \ + (s)->p++; \ + (v) <<= 8; \ + (v) |= *((unsigned char*)((s)->p)); \ + (s)->p++; \ + (v) <<= 8; \ + (v) |= *((unsigned char*)((s)->p)); \ + (s)->p++; \ +} + +/******************************************************************************/ #define out_uint8(s, v) \ { \ *((s)->p) = (unsigned char)(v); \ @@ -278,6 +395,85 @@ } /******************************************************************************/ +#if defined(B_ENDIAN) || defined(NEED_ALIGN) +#define out_uint64_le(s, v) \ +{ \ + *((s)->p) = (unsigned char)((v) >> 0); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 8); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 16); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 24); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 32); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 40); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 48); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 56); \ + (s)->p++; \ +} +#else +#define out_uint64_le(s, v) \ +{ \ + *((unsigned long long*)((s)->p)) = (v); \ + (s)->p += 8; \ +} +#endif + +/******************************************************************************/ +#if defined(B_ENDIAN) || defined(NEED_ALIGN) +#define out_int64_le(s, v) \ +{ \ + *((s)->p) = (unsigned char)((v) >> 0); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 8); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 16); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 24); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 32); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 40); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 48); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 56); \ + (s)->p++; \ +} +#else +#define out_int64_le(s, v) \ +{ \ + *((unsigned long long*)((s)->p)) = (v); \ + (s)->p += 8; \ +} +#endif + +/******************************************************************************/ +#define out_uint64_be(s, v) \ +{ \ + *((s)->p) = (unsigned char)((v) >> 56); \ + s->p++; \ + *((s)->p) = (unsigned char)((v) >> 48); \ + s->p++; \ + *((s)->p) = (unsigned char)((v) >> 40); \ + s->p++; \ + *((s)->p) = (unsigned char)((v) >> 32); \ + s->p++; \ + *((s)->p) = (unsigned char)((v) >> 24); \ + s->p++; \ + *((s)->p) = (unsigned char)((v) >> 16); \ + s->p++; \ + *((s)->p) = (unsigned char)((v) >> 8); \ + s->p++; \ + *((s)->p) = (unsigned char)(v); \ + (s)->p++; \ +} + +/******************************************************************************/ #define in_uint8p(s, v, n) \ { \ (v) = (s)->p; \ diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/rdpdr.h posixrdp/posixxrdp.orig/common/rdpdr.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/rdpdr.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/rdpdr.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,574 @@ +#ifndef FUSE_USE_VERSION +#define FUSE_USE_VERSION 26 +#endif + +#ifndef __XRDP_RDPDR_DEF__ +#define __XRDP_RDPDR_DEF__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "thread_calls.h" + +#include "devredir_defs.h" +#include "drdynvc_defs.h" +#include "recording_defs.h" + +#define htobel(x) (htonl(x)) + +struct buffer; +struct request; +struct list_head; +struct read_chunk; +struct _rdpfs_file; +struct _rdpfs; +struct _rdpport; +struct _rdpprint; +struct _rdpsc; + +typedef struct _filelist_entry { + int index; + char filename[512]; + uint64_t CreationTime; + uint64_t LastAccessTime; + uint64_t LastWriteTime; + uint64_t ChangeTime; + uint64_t EndOfFile; + uint64_t AllocationSize; + uint32_t FileAttributes; + uint32_t NumberOfLinks; + uint8_t DeletePending; + uint8_t Directory; + uint32_t EaSize; +} filelist_entry; + +typedef struct _filelist { + #ifndef FILELIST_MAX + #define FILELIST_MAX 4096 + #endif + int count; + filelist_entry * files[FILELIST_MAX]; +} filelist; + +typedef struct buffer { + uint8_t *p; + size_t len; + size_t size; +} rdpfs_buffer; + +typedef struct list_head { + struct list_head * prev; + struct list_head * next; +} rdpfs_list_head; + +typedef void (*request_func)(struct request *); + +typedef struct request { + unsigned int want_reply; + sem_t ready; + uint8_t reply_type; + int replied; + int error; + struct buffer reply; + struct timeval start; + void *data; + request_func end_func; + size_t len; + struct list_head list; +} rdpfs_req; + +typedef struct _read_chunk { + sem_t ready; + off_t offset; + size_t size; + struct buffer data; + int refs; + int res; + long modifver; +} read_chunk; + +typedef struct _rdpfs_file { + struct buffer handle; + struct list_head write_reqs; + pthread_cond_t write_finished; + int write_error; + struct read_chunk * readahead; + off_t next_pos; + int is_seq; + int connver; + int modifver; + int refs; +} rdpfs_file; + +#ifndef _FUSE_LOWLEVEL_H_ +struct fuse_chan_ops { + int(*receive )(struct fuse_chan **chp, char *buf, size_t size); + int(*send )(struct fuse_chan *ch, const struct iovec iov[], size_t count); + void(*destroy )(struct fuse_chan *ch); +}; +#endif + +struct fuse_chan { + struct fuse_chan_ops op; + struct fuse_session *se; + int fd; + size_t bufsize; + void *data; + int compat; +}; + +typedef struct _rdpfs_data { + int callback_index; + int FileId; + int length; + void * data; +} rdpfs_data, rdpport_data, rdpprint_data, rdpsc_data; + +struct _callback; + +#ifndef __RDPFS_STATE__ +#define __RDPFS_STATE__ +struct rdpfs_state { + FILE * logfile; + char * rootdir; +}; + +#define RDPFS_DATA ((struct rdpfs_state *) fuse_get_context()->private_data) + +//#define RDPFS_DATA ((struct rdpfs_state *) ((fuse_get_context() == NULL) ? NULL : fuse_get_context()->private_data))) +#endif + +typedef struct _rdpfs { + + #ifndef MAX_PENDING +// #define MAX_PENDING 512 + #define MAX_PENDING 25 + #endif + #ifndef MAX_REQID + #define MAX_REQID 25 + #endif + #define ANY_FS 0x00000100 + #define RDP_FS 0x00000100 + #define RDPFS_CONTEXT_MAGIC 0xdadee777 + + FILE * logfile; + char * rootdir; + uint32_t magic; + uint32_t device_id; + int type; /* 0x00000100 = RDPFS */ + int fd; + struct trans * ccon; + int handler_pid; + int parent_pid; + int child_pid; + int parent_sck; + int child_sck; + int top_opid; + int pending_opids[MAX_PENDING]; +// struct _callback * callbacks[MAX_PENDING]; +// struct _callback * callbacks; +// struct _callback ** callbacks; + struct _callback callbacks[MAX_PENDING]; + struct _rdpfs * g_fs; + int g_device_index; + int g_fs_index; + int connver; + int server_version; + int debug; + tc_t mut; + tc_t mut_write; + unsigned char processing_thread_started; + int fhandle; + char * mountpoint; + char * dos_name; + struct fuse * fuse; + struct fuse_chan * ch; + struct fuse_args rdpfs_args; + int transform_symlinks; + int detect_uid; + unsigned int max_read; + unsigned int max_write; + int sync_write; + int sync_read; + int foreground; + int reconnect; + char * host; + char * base_path; + unsigned int randseed; + unsigned int remote_uid; + unsigned int local_uid; + int remote_uid_detected; + unsigned int blksize; + char * progname; + int ext_posix_rename; + int ext_statvfs; + mode_t mnt_mode; + unsigned char initialized; + + /* statistics */ + uint64_t bytes_sent; + uint64_t bytes_received; + uint64_t num_sent; + uint64_t num_received; + unsigned int min_rtt; + unsigned int max_rtt; + uint64_t total_rtt; + unsigned int num_connect; + + /* locking */ + tc_t g_cv_readdir; + + tc_t g_mutex_pcon_fs; + tc_t g_mutex_fs; + tc_t g_mutex_parent_fs; + tc_t g_mutex_fuse; + tc_t g_mutex_fsop; + tc_t g_mutex_reqid_fs; + tc_t g_mutex_getattr; + + tc_p cv_readdir; + tc_p mutex_pcon_fs; + tc_p mutex_fs; + tc_p mutex_parent_fs; + tc_p mutex_fuse; + tc_p mutex_fsop; + tc_p mutex_reqid_fs; + tc_p mutex_getattr; + +} rdpfs, rdpfs_t, rdpfs_context_t; + +#define RDPFS_DECS rdpfs * g_fs __attribute__ ((unused)) = (rdpfs *)RDPFS_DATA; \ + int g_fd __attribute__ ((unused)) = g_fs->fd; \ + callback * g_reqids __attribute__ ((unused)) = (callback *)(g_fs->callbacks); \ + uint32_t device_id __attribute__ ((unused)) = 0; + + +typedef struct _rdpport { + #define ANY_PORT 0x00000200 + #define SERIAL_PORT 0x00000201 + #define PARALLEL_PORT 0x00000202 + uint32_t device_id; + int type; /* 0x00000201 = serial; 0x00000202 = parallel */ + int fd; + struct trans * ccon; + int handler_pid; + int parent_pid; + int child_pid; + int parent_sck; + int child_sck; + int top_opid; + int pending_opids[MAX_PENDING]; + struct _callback * callbacks[MAX_PENDING]; + struct _rdpport * g_port; + int g_device_index; + int g_port_index; + int connver; + int server_version; + int debug; + pthread_mutex_t lock; + pthread_mutex_t lock_write; + int processing_thread_started; + int fhandle; /* the file descriptor corresponding to the opened serial/parallel port */ + char * file_path; + char * dos_name; +} rdpport_t; + +typedef struct _rdpprint { + #define ANY_PRINTER 0x00000400 + #define NORMAL_PRINTER 0x00000401 + #define XPS_PRINTER 0x00000402 + uint32_t device_id; + int type; /* 0x00000401 = normal; 0x00000402 = xps */ + int fd; + struct trans * ccon; + int handler_pid; + int parent_pid; + int child_pid; + int parent_sck; + int child_sck; + int top_opid; + int pending_opids[MAX_PENDING]; + struct _callback * callbacks[MAX_PENDING]; + struct _rdpprint * g_printer; + int g_device_index; + int g_printer_index; + int connver; + int server_version; + int debug; + pthread_mutex_t lock; + pthread_mutex_t lock_write; + int processing_thread_started; + int fhandle; /* the file descriptor corresponding to the opened printer */ + char * file_path; + char * dos_name; +} rdpprint; + +typedef struct _rdpsc { + #define RDP_SC 0x00000800 + uint32_t device_id; + int type; /* 0x00000800 = RDP smartcard */ + int fd; + struct trans * ccon; + int handler_pid; + int parent_pid; + int child_pid; + int parent_sck; + int child_sck; + int top_opid; + int pending_opids[MAX_PENDING]; + struct _callback * callbacks[MAX_PENDING]; + struct _rdpport * g_sc; + int g_device_index; + int g_smartcard_index; + int connver; + int server_version; + int debug; + pthread_mutex_t lock; + pthread_mutex_t lock_write; + int processing_thread_started; + int fhandle; /* the file descriptor corresponding to the opened smart card */ + char * file_path; + char * dos_name; +} rdpsc; + +typedef union _rdpdevicetypes { + rdpfs fs; + rdpport_t port; + rdpprint printer; + rdpsc smartcard; +} rdpdev; + +enum { + KEY_HELP, + KEY_HELP_NOHEADER, + KEY_VERSION, + KEY_KEEP, +}; + +struct helper_opts { + int singlethread; + int foreground; + int fsname; + char *mountpoint; +}; + +#define FUSE_HELPER_OPT(t, p) { t, offsetof(struct helper_opts, p), 1 } + +/* Function signatures: */ + +unsigned long rdpfs_hash(unsigned char *); + +#define RDP_ERROR 0x01000000 +#define RDP_REPLY 0x08000000 +#define RDP_INIT 0x0000100F +#define RDP_OPEN 0x00001000 +#define RDP_CLOSE 0x00002000 +#define RDP_READ 0x00004000 +#define RDP_WRITE 0x00008000 +#define RDP_IOCTL 0x00008D01 + +/* devredir <--> fs_handler opcodes */ +#define RDPFS_NEGOTIATE 0x00100000 +#define RDPFS_LOOKUP 0x00100001 +#define RDPFS_FORGET 0x00100002 +#define RDPFS_READLINK 0x001040F0 +#define RDPFS_GETATTR 0x00104D00 +#define RDPFS_SETATTR 0x00108D00 +#define RDPFS_MKNOD 0x00100005 +#define RDPFS_MKDIR 0x00100008 +#define RDPFS_UNLINK 0x001080A0 +#define RDPFS_RELEASE 0x00102000 +#define RDPFS_RMDIR 0x001080A1 +#define RDPFS_SYMLINK 0x00101140 +#define RDPFS_RENAME 0x001081A0 +#define RDPFS_LINK 0x00101180 +#define RDPFS_CHMOD 0x00108200 +#define RDPFS_CHOWN 0x00108210 +#define RDPFS_TRUNCATE 0x00108400 +#define RDPFS_UTIME 0x00108800 +#define RDPFS_OPEN 0x00101000 +#define RDPFS_READ 0x00104000 +#define RDPFS_WRITE 0x00108000 +#define RDPFS_STATFS 0x00104002 +#define RDPFS_FLUSH 0x00108080 +#define RDPFS_FSYNC 0x00108B40 +#define RDPFS_GETXATTR 0x00104F00 +#define RDPFS_SETXATTR 0x00108F00 +#define RDPFS_LISTXATTR 0x00104F10 +#define RDPFS_REMOVEXATTR 0x00108FA0 +#define RDPFS_OPENDIR 0x00101001 +#define RDPFS_READDIR 0x00104001 +#define RDPFS_RELEASEDIR 0x00102001 +#define RDPFS_FSYNCDIR 0x00108B41 +#define RDPFS_INIT 0x0010100F +#define RDPFS_DESTROY 0x0010200F +#define RDPFS_ACCESS 0x00104E00 +#define RDPFS_CREATE 0x00101110 +#define RDPFS_FTRUNCATE 0x00108440 +#define RDPFS_FGETATTR 0x00104D40 +#define RDPFS_IOCTL 0x00108D01 +#define RDPFS_BMAP 0x00104202 +#define RDPFS_POLL 0x00104303 +#define RDPFS_FSCTL 0x00108C02 +#define RDPFS_END 0x0010200E +#define RDPFS_ERROR 0x01000000 +#define RDPFS_REPLY 0x08000000 + +#define RDPPORT_INIT 0x0001100F +#define RDPPORT_OPEN 0x00011000 +#define RDPPORT_READ 0x00014000 +#define RDPPORT_WRITE 0x00018000 +#define RDPPORT_CLOSE 0x00012000 +#define RDPPORT_IOCTL 0x00018D01 +#define RDPPORT_DESTROY 0x0001200F +#define RDPPORT_ERROR 0x01000000 +#define RDPPORT_REPLY 0x08000000 +#define RDPPORT_END 0x0001200E + +#define RDPPRINT_INIT 0x0002100F +#define RDPPRINT_OPEN 0x00021000 +#define RDPPRINT_READ 0x00024000 +#define RDPPRINT_WRITE 0x00028000 +#define RDPPRINT_CLOSE 0x00022000 +#define RDPPRINT_IOCTL 0x00028D01 +#define RDPPRINT_DESTROY 0x0002200F +#define RDPPRINT_ERROR 0x01000000 +#define RDPPRINT_REPLY 0x08000000 +#define RDPPRINT_END 0x0002200E + +#define RDPSC_INIT 0x0008100F +#define RDPSC_OPEN 0x00081000 +#define RDPSC_READ 0x00084000 +#define RDPSC_WRITE 0x00088000 +#define RDPSC_CLOSE 0x00082000 +#define RDPSC_IOCTL 0x00088D01 +#define RDPSC_DESTROY 0x0008200F +#define RDPSC_ERROR 0x01000000 +#define RDPSC_REPLY 0x08000000 +#define RDPSC_END 0x0008200E + + +enum rdp_message_types { + RDP_M_PING = 0x00, + RDP_M_IOCTL = 0x01, + RDP_M_SETMCTRL = 0x02, + RDP_M_GETMCTRL = 0x03, + RDP_M_GETSTATUS = 0x04, + RDP_M_ADDPORT = 0x05, + RDP_M_OPEN = 0x06, + RDP_M_CLOSE = 0x07, + RDP_M_READ = 0x08, + RDP_M_WRITE = 0x09, + RDP_M_DATA = 0x0A, + RDP_M_START = 0x0B, + RDP_M_STOP = 0x0C, + RDP_M_GETBAUD = 0x0D, + RDP_M_SETBAUD = 0x0E, + RDP_M_TXEMPTY = 0x0F, + RDP_M_TXFULL = 0x10, + RDP_M_TXSTOP = 0x11, + RDP_M_TXSTART = 0x12, + RDP_M_RXEMPTY = 0x13, + RDP_M_RXFULL = 0x14, + RDP_M_RXSTOP = 0x15, + RDP_M_RXSTART = 0x16, + RDP_M_MSENABLE = 0x17, + RDP_M_BREAKCTL = 0x18, + RDP_M_SETTERMIOS = 0x19, + RDP_M_GETTERMIOS = 0x1A, + RDP_M_XCHAR = 0x1B, + RDP_M_ASYNC = 0x40, + RDP_M_REPLY = 0x80, +}; + +#define CMD_TO_STRING_ARRAY_DEF { \ + [0x00] = "RDP_M_PING", \ + [0x01] = "RDP_M_IOCTL", \ + [0x02] = "RDP_M_SETMCTRL", \ + [0x03] = "RDP_M_GETMCTRL", \ + [0x04] = "RDP_M_GETSTATUS", \ + [0x05] = "RDP_M_ADDPORT", \ + [0x06] = "RDP_M_OPEN", \ + [0x07] = "RDP_M_CLOSE", \ + [0x08] = "RDP_M_READ", \ + [0x09] = "RDP_M_WRITE", \ + [0x0A] = "RDP_M_DATA", \ + [0x0B] = "RDP_M_START", \ + [0x0C] = "RDP_M_STOP", \ + [0x0D] = "RDP_M_GETBAUD", \ + [0x0E] = "RDP_M_SETBAUD", \ + [0x0F] = "RDP_M_TXEMPTY", \ + [0x10] = "RDP_M_TXFULL", \ + [0x11] = "RDP_M_TXSTOP", \ + [0x12] = "RDP_M_TXSTART", \ + [0x13] = "RDP_M_RXEMPTY", \ + [0x14] = "RDP_M_RXFULL", \ + [0x15] = "RDP_M_RXSTOP", \ + [0x16] = "RDP_M_RXSTART", \ + [0x17] = "RDP_M_MSENABLE", \ + [0x18] = "RDP_M_BREAKCTL", \ + [0x19] = "RDP_M_SETTERMIOS", \ + [0x1A] = "RDP_M_GETTERMIOS", \ + [0x1B] = "RDP_M_XCHAR", \ + [0x40] = "RDP_M_ASYNC", \ + [0x80] = "RDP_M_REPLY", \ +} + +#define RDP_PACKET_MAGIC 0xfeeddeef + +typedef struct rdpfs_shm { + DR_DEVICELIST_ANNOUNCE_STATIC client_devicelist; + DEVICE_ANNOUNCE * DeviceList_arr[96]; + struct _rdpfs * fs_arr[24]; + struct _rdpfs fs_arr_s[24]; + rdpport_t * port_arr[24]; + rdpport_t port_arr_s[24]; + rdpprint * print_arr[24]; + rdpprint print_arr_s[24]; + rdpsc * sc_arr[24]; + rdpsc sc_arr_s[24]; +} rdpfs_shm_t, * rdpfs_shm_p; + +typedef struct rdpfs_shm_blob { + uint32_t len; + rdpfs_shm_t shm; +} rdpfs_shm_blob_t; + +void * g_shm; +size_t * g_shm_len; +int * g_shm_sem; + +tc_p mutex_client_devicelist; +/* +tc_p mutex_fs_arr; +tc_p mutex_port_arr; +tc_p mutex_printer_arr; +tc_p mutex_smartcard_arr; +*/ + + + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/rdpdr_methods.c posixrdp/posixxrdp.orig/common/rdpdr_methods.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/rdpdr_methods.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/rdpdr_methods.c 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,4928 @@ + +#include "os_calls.h" +#include "rdpdr.h" +#include "rdpdr_methods.h" +#include "parse.h" + + +/********************************************************************** + * static declarations + **********************************************************************/ + +static int APP_CC setPath_DR_DRIVE_QUERY_DIRECTORY_REQ(struct _DR_DRIVE_QUERY_DIRECTORY_REQ *, const char *); + + +/********************************************************************** + * global variables + **********************************************************************/ + + +/********************************************************************** + * BEGIN: CONSTRUCTORS + **********************************************************************/ + +int APP_CC construct_RDPDR_HEADER(RDPDR_HEADER * self) { + int rv = 0; + + g_memset(self,0,sizeof(RDPDR_HEADER)); + self->Component = RDPDR_CTYP_CORE; + self->out = &send_RDPDR_HEADER; + self->in = &get_RDPDR_HEADER; + + return rv; +} + +int APP_CC construct_CAPABILITY_HEADER(CAPABILITY_HEADER * self) { + int rv = 0; + + g_memset(self,0,sizeof(CAPABILITY_HEADER)); + self->out = &send_CAPABILITY_HEADER; + self->in = &get_CAPABILITY_HEADER; + + return rv; +} + +int APP_CC construct_CAPABILITY_SET(CAPABILITY_SET * self) { + int rv = 0; + + g_memset(self,0,sizeof(CAPABILITY_SET)); + self->out = &send_CAPABILITY_SET; + self->in = &get_CAPABILITY_SET; + + return rv; +} + +int APP_CC construct_DEVICE_ANNOUNCE(DEVICE_ANNOUNCE * self) { + int rv = 0; + + g_memset(self,0,sizeof(DEVICE_ANNOUNCE)); + self->out = &send_DEVICE_ANNOUNCE; + self->in = &get_DEVICE_ANNOUNCE; + + return rv; +} + +int APP_CC construct_DR_DEVICE_IOREQUEST(DR_DEVICE_IOREQUEST * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DEVICE_IOREQUEST)); + construct_RDPDR_HEADER(&(self->Header)); + self->Header.Component = RDPDR_CTYP_CORE; + self->Header.PacketId = PAKID_CORE_DEVICE_IOREQUEST; + self->Header.out = &send_RDPDR_HEADER; + self->Header.in = &get_RDPDR_HEADER; + self->Header.__destructor = NULL; + self->out = &send_DR_DEVICE_IOREQUEST; + self->in = &get_DR_DEVICE_IOREQUEST; + + return rv; +} + +int APP_CC construct_DR_CREATE_REQ(DR_CREATE_REQ * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_CREATE_REQ)); + construct_RDPDR_HEADER(&(self->DeviceIoRequest.Header)); + construct_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest)); + self->DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + self->DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + self->DeviceIoRequest.Header.__destructor = NULL; + self->DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + self->DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + self->DeviceIoRequest.__destructor = NULL; + self->out = &send_DR_CREATE_REQ; + self->in = &get_DR_CREATE_REQ; + self->DeviceIoRequest.MajorFunction = IRP_MJ_CREATE; + self->CreateDisposition = FILE_OPEN; + self->PathLength = 2; + + return rv; +} + +int APP_CC construct_DR_CLOSE_REQ(DR_CLOSE_REQ * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_CLOSE_REQ)); + construct_RDPDR_HEADER(&(self->DeviceIoRequest.Header)); + construct_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest)); + self->DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + self->DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + self->DeviceIoRequest.Header.__destructor = NULL; + self->DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + self->DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + self->DeviceIoRequest.__destructor = NULL; + self->out = &send_DR_CLOSE_REQ; + self->in = &get_DR_CLOSE_REQ; + self->DeviceIoRequest.MajorFunction = IRP_MJ_CLOSE; + + return rv; +} + +int APP_CC construct_DR_READ_REQ(DR_READ_REQ * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_READ_REQ)); + construct_RDPDR_HEADER(&(self->DeviceIoRequest.Header)); + construct_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest)); + self->in = &get_DR_READ_REQ; + self->out = &send_DR_READ_REQ; + self->DeviceIoRequest.MajorFunction = IRP_MJ_READ; + + return rv; +} + +int APP_CC construct_DR_WRITE_REQ(DR_WRITE_REQ * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_WRITE_REQ)); + construct_RDPDR_HEADER(&(self->DeviceIoRequest.Header)); + construct_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest)); + self->in = &get_DR_WRITE_REQ; + self->out = &send_DR_WRITE_REQ; + self->DeviceIoRequest.MajorFunction = IRP_MJ_WRITE; + + return rv; +} + +int APP_CC construct_DR_CONTROL_REQ(DR_CONTROL_REQ * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_CONTROL_REQ)); + construct_RDPDR_HEADER(&(self->DeviceIoRequest.Header)); + construct_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest)); + self->in = &get_DR_CONTROL_REQ; + self->out = &send_DR_CONTROL_REQ; + self->DeviceIoRequest.MajorFunction = IRP_MJ_DEVICE_CONTROL; + + return rv; +} + +int APP_CC construct_DR_DEVICE_IOCOMPLETION(DR_DEVICE_IOCOMPLETION * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DEVICE_IOCOMPLETION)); + construct_RDPDR_HEADER(&(self->Header)); + self->Header.in = &get_RDPDR_HEADER; + self->Header.out = &send_RDPDR_HEADER; + self->Header.__destructor = NULL; + self->in = &get_DR_DEVICE_IOCOMPLETION; + self->out = &send_DR_DEVICE_IOCOMPLETION; + + return rv; +} + +int APP_CC construct_DR_CREATE_RSP(DR_CREATE_RSP * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_CREATE_RSP)); + construct_RDPDR_HEADER(&(self->DeviceIoReply.Header)); + construct_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply)); + self->out = &send_DR_CREATE_RSP; + self->in = &get_DR_CREATE_RSP; + + return rv; +} + +int APP_CC construct_DR_CLOSE_RSP(DR_CLOSE_RSP * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_CLOSE_RSP)); + construct_RDPDR_HEADER(&(self->DeviceIoReply.Header)); + construct_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply)); + self->out = &send_DR_CLOSE_RSP; + self->in = &get_DR_CLOSE_RSP; + + return rv; +} + +int APP_CC construct_DR_READ_RSP(DR_READ_RSP * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_READ_RSP)); + construct_RDPDR_HEADER(&(self->DeviceIoReply.Header)); + construct_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply)); + self->out = &send_DR_READ_RSP; + self->in = &get_DR_READ_RSP; + + return rv; +} + +int APP_CC construct_DR_WRITE_RSP(DR_WRITE_RSP * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_WRITE_RSP)); + construct_RDPDR_HEADER(&(self->DeviceIoReply.Header)); + construct_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply)); + self->out = &send_DR_WRITE_RSP; + self->in = &get_DR_WRITE_RSP; + + return rv; +} + +int APP_CC construct_DR_CONTROL_RSP(DR_CONTROL_RSP * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_CONTROL_RSP)); + construct_RDPDR_HEADER(&(self->DeviceIoReply.Header)); + construct_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply)); + self->out = &send_DR_CONTROL_RSP; + self->in = &get_DR_CONTROL_RSP; + + return rv; +} + +int APP_CC construct_RDP_LOCK_INFO(RDP_LOCK_INFO * self) { + int rv = 0; + + g_memset(self,0,sizeof(RDP_LOCK_INFO)); + self->out = &send_RDP_LOCK_INFO; + self->in = &get_RDP_LOCK_INFO; + + return rv; +} + +int APP_CC construct_DR_CORE_DEVICE_ANNOUNCE_RSP(DR_CORE_DEVICE_ANNOUNCE_RSP * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_CORE_DEVICE_ANNOUNCE_RSP)); + construct_RDPDR_HEADER(&(self->Header)); + self->out = &send_DR_CORE_DEVICE_ANNOUNCE_RSP; + self->in = &get_DR_CORE_DEVICE_ANNOUNCE_RSP; + + return rv; +} + +int APP_CC construct_DR_CORE_SERVER_ANNOUNCE_REQ(DR_CORE_SERVER_ANNOUNCE_REQ * self) { + int rv = 0; + + /* [MS-RDPEFS] — v20091104 @ p.31 */ + g_memset(self,0,sizeof(DR_CORE_SERVER_ANNOUNCE_REQ)); + construct_RDPDR_HEADER(&(self->Header)); + self->Header.Component = RDPDR_CTYP_CORE; + self->Header.PacketId = PAKID_CORE_SERVER_ANNOUNCE; + self->VersionMajor = 0x0001; + self->VersionMinor = 0x000A; + self->out = &send_DR_CORE_SERVER_ANNOUNCE_REQ; + self->in = &get_DR_CORE_SERVER_ANNOUNCE_REQ; + + return rv; +} + +int APP_CC construct_DR_CORE_SERVER_ANNOUNCE_RSP(DR_CORE_SERVER_ANNOUNCE_RSP * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_CORE_SERVER_ANNOUNCE_RSP)); + construct_RDPDR_HEADER(&(self->Header)); + self->in = &get_DR_CORE_SERVER_ANNOUNCE_RSP; + self->out = &send_DR_CORE_SERVER_ANNOUNCE_RSP; + + return rv; +} + +int APP_CC construct_DR_CORE_CLIENT_NAME_REQ(DR_CORE_CLIENT_NAME_REQ * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_CORE_CLIENT_NAME_REQ)); + construct_RDPDR_HEADER(&(self->Header)); + self->in = &get_DR_CORE_CLIENT_NAME_REQ; + self->out = &send_DR_CORE_CLIENT_NAME_REQ; + + return rv; +} + +int APP_CC construct_DR_CORE_SERVER_CLIENTID_CONFIRM(DR_CORE_SERVER_CLIENTID_CONFIRM * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_CORE_SERVER_CLIENTID_CONFIRM)); + construct_RDPDR_HEADER(&(self->Header)); + self->in = &get_DR_CORE_SERVER_CLIENTID_CONFIRM; + self->out = &send_DR_CORE_SERVER_CLIENTID_CONFIRM; + + return rv; +} + +int APP_CC construct_DR_CORE_CAPABILITY_REQ(DR_CORE_CAPABILITY_REQ * self) { + int rv = 0; + + GENERAL_CAPS_SET * generalcap = (GENERAL_CAPS_SET *)NULL; + PRINTER_CAPS_SET * printercap = (PRINTER_CAPS_SET *)NULL; + PORT_CAPS_SET * portcap = (PORT_CAPS_SET *)NULL; + DRIVE_CAPS_SET * drivecap = (DRIVE_CAPS_SET *)NULL; + SMARTCARD_CAPS_SET * smartcardcap = (SMARTCARD_CAPS_SET *)NULL; + + g_memset(self,0,sizeof(DR_CORE_CAPABILITY_REQ)); + + generalcap = RDPDR_NEW(GENERAL_CAPS_SET); + printercap = RDPDR_NEW(PRINTER_CAPS_SET); + portcap = RDPDR_NEW(PORT_CAPS_SET); + drivecap = RDPDR_NEW(DRIVE_CAPS_SET); + smartcardcap = RDPDR_NEW(SMARTCARD_CAPS_SET); + self->Header.Component = RDPDR_CTYP_CORE; + self->Header.PacketId = PAKID_CORE_SERVER_CAPABILITY; + self->out = &send_DR_CORE_CAPABILITY_REQ; + self->in = &get_DR_CORE_CAPABILITY_REQ; + + return rv; +} + +int APP_CC construct_GENERAL_CAPS_SET(GENERAL_CAPS_SET * self) { + int rv = 0; + + g_memset(self,0,sizeof(GENERAL_CAPS_SET)); + construct_CAPABILITY_HEADER(&(self->Header)); + self->Header.CapabilityType = CAP_GENERAL_TYPE; + self->Header.CapabilityLength = 8; + self->Header.Version = GENERAL_CAPABILITY_VERSION_02; + self->protocolMajorVersion = 0x0001; + self->protocolMinorVersion = 0x000C; + self->ioCode1 = RDPDR_IRP_MJ_CREATE | RDPDR_IRP_MJ_CLEANUP | RDPDR_IRP_MJ_CLOSE | RDPDR_IRP_MJ_READ | RDPDR_IRP_MJ_WRITE | RDPDR_IRP_MJ_FLUSH_BUFFERS | RDPDR_IRP_MJ_SHUTDOWN | RDPDR_IRP_MJ_DEVICE_CONTROL | RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION | RDPDR_IRP_MJ_SET_VOLUME_INFORMATION | RDPDR_IRP_MJ_QUERY_INFORMATION | RDPDR_IRP_MJ_SET_INFORMATION | RDPDR_IRP_MJ_DIRECTORY_CONTROL | RDPDR_IRP_MJ_LOCK_CONTROL; + self->extendedPDU = RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | RDPDR_USER_LOGGEDON_PDU; + self->extraFlags1 = ENABLE_ASYNCIO; + self->Header.out = &send_CAPABILITY_HEADER; + self->Header.in = &get_CAPABILITY_HEADER; + self->out = &send_GENERAL_CAPS_SET; + self->in = &get_GENERAL_CAPS_SET; + + return rv; +} + +int APP_CC construct_PRINTER_CAPS_SET(PRINTER_CAPS_SET * self) { + int rv = 0; + + g_memset(self,0,sizeof(PRINTER_CAPS_SET)); + construct_CAPABILITY_HEADER(&(self->Header)); + self->Header.out = &send_CAPABILITY_HEADER; + self->Header.in = &get_CAPABILITY_HEADER; + self->out = &send_PRINTER_CAPS_SET; + self->in = &get_PRINTER_CAPS_SET; + self->Header.CapabilityType = CAP_PRINTER_TYPE; + self->Header.CapabilityLength = 8; + self->Header.Version = PRINT_CAPABILITY_VERSION_01; + + return rv; +} + +int APP_CC construct_PORT_CAPS_SET(PORT_CAPS_SET * self) { + int rv = 0; + + g_memset(self,0,sizeof(PORT_CAPS_SET)); + construct_CAPABILITY_HEADER(&(self->Header)); + self->Header.out = &send_CAPABILITY_HEADER; + self->Header.in = &get_CAPABILITY_HEADER; + self->out = &send_PORT_CAPS_SET; + self->in = &get_PORT_CAPS_SET; + self->Header.CapabilityType = CAP_PORT_TYPE; + self->Header.CapabilityLength = 8; + self->Header.Version = PORT_CAPABILITY_VERSION_01; + + return rv; +} + +int APP_CC construct_DRIVE_CAPS_SET(DRIVE_CAPS_SET * self) { + int rv = 0; + + g_memset(self,0,sizeof(DRIVE_CAPS_SET)); + construct_CAPABILITY_HEADER(&(self->Header)); + self->Header.out = &send_CAPABILITY_HEADER; + self->Header.in = &get_CAPABILITY_HEADER; + self->out = &send_DRIVE_CAPS_SET; + self->in = &get_DRIVE_CAPS_SET; + self->Header.CapabilityType = CAP_DRIVE_TYPE; + self->Header.CapabilityLength = 8; + self->Header.Version = DRIVE_CAPABILITY_VERSION_02; + + return rv; +} + +int APP_CC construct_SMARTCARD_CAPS_SET(SMARTCARD_CAPS_SET * self) { + int rv = 0; + + g_memset(self,0,sizeof(SMARTCARD_CAPS_SET)); + construct_CAPABILITY_HEADER(&(self->Header)); + self->Header.out = &send_CAPABILITY_HEADER; + self->Header.in = &get_CAPABILITY_HEADER; + self->out = &send_SMARTCARD_CAPS_SET; + self->in = &get_SMARTCARD_CAPS_SET; + self->Header.CapabilityType = CAP_SMARTCARD_TYPE; + self->Header.CapabilityLength = 8; + self->Header.Version = SMARTCARD_CAPABILITY_VERSION_01; + + return rv; +} + +int APP_CC construct_DR_CORE_DEVICELIST_ANNOUNCE_REQ(DR_CORE_DEVICELIST_ANNOUNCE_REQ * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_CORE_DEVICELIST_ANNOUNCE_REQ)); + construct_RDPDR_HEADER(&(self->Header)); + self->out = &send_DR_CORE_DEVICELIST_ANNOUNCE_REQ; + self->in = &get_DR_CORE_DEVICELIST_ANNOUNCE_REQ; + + return rv; +} + +int APP_CC construct_DR_DEVICELIST_ANNOUNCE(DR_DEVICELIST_ANNOUNCE * self) { + int rv = 0; + int idx = 0; + + //g_memset(self,0,sizeof(DR_DEVICELIST_ANNOUNCE)); + construct_RDPDR_HEADER(&(self->Header)); + self->Header.Component = RDPDR_CTYP_CORE; + self->Header.PacketId = PAKID_CORE_DEVICELIST_ANNOUNCE; + self->Header.out = &send_RDPDR_HEADER; + self->Header.in = &get_RDPDR_HEADER; + self->Header.__destructor = NULL; + self->out = &send_DR_DEVICELIST_ANNOUNCE; + self->in = &get_DR_DEVICELIST_ANNOUNCE; + self->__destructor = NULL; + + if (self->DeviceCount > 0) { + self->DeviceList = (DEVICE_ANNOUNCE **)g_malloc(sizeof(size_t) * self->DeviceCount, 1); + for (idx = 0; idx < self->DeviceCount; idx++) { + self->DeviceList[idx] = (DEVICE_ANNOUNCE *)g_malloc(sizeof(DEVICE_ANNOUNCE), 1); + } + } + + return rv; +} + +int APP_CC construct_DR_DEVICELIST_REMOVE(DR_DEVICELIST_REMOVE * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DEVICELIST_REMOVE)); + construct_RDPDR_HEADER(&(self->Header)); + self->out = &send_DR_DEVICELIST_REMOVE; + self->in = &get_DR_DEVICELIST_REMOVE; + + return rv; +} + +int APP_CC construct_DR_DRIVE_CORE_DEVICE_IOREQUEST(DR_DRIVE_CORE_DEVICE_IOREQUEST * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_CORE_DEVICE_IOREQUEST)); + construct_RDPDR_HEADER(&(self->Header.Header)); + construct_DR_DEVICE_IOREQUEST(&(self->Header)); + self->Header.Header.out = &send_RDPDR_HEADER; + self->Header.Header.in = &get_RDPDR_HEADER; + self->Header.Header.__destructor = NULL; + self->Header.out = &send_DR_DEVICE_IOREQUEST; + self->Header.in = &get_DR_DEVICE_IOREQUEST; + self->Header.__destructor = NULL; + self->out = &send_DR_DRIVE_CORE_DEVICE_IOREQUEST; + self->in = &get_DR_DRIVE_CORE_DEVICE_IOREQUEST; + self->__destructor = NULL; + + return rv; +} + +int APP_CC construct_DR_DRIVE_CREATE_REQ(DR_DRIVE_CREATE_REQ * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_CREATE_REQ)); + construct_RDPDR_HEADER(&(self->DeviceCreateRequest.DeviceIoRequest.Header)); + construct_DR_DEVICE_IOREQUEST(&(self->DeviceCreateRequest.DeviceIoRequest)); + construct_DR_CREATE_REQ(&(self->DeviceCreateRequest)); + self->DeviceCreateRequest.DeviceIoRequest.Header.Component = RDPDR_CTYP_CORE; + self->DeviceCreateRequest.DeviceIoRequest.Header.PacketId = PAKID_CORE_DEVICE_IOREQUEST; + self->DeviceCreateRequest.DeviceIoRequest.MajorFunction = IRP_MJ_CREATE; + self->DeviceCreateRequest.DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + self->DeviceCreateRequest.DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + self->DeviceCreateRequest.DeviceIoRequest.Header.__destructor = NULL; + self->DeviceCreateRequest.DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + self->DeviceCreateRequest.DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + self->DeviceCreateRequest.DeviceIoRequest.__destructor = NULL; + self->DeviceCreateRequest.out = &send_DR_CREATE_REQ; + self->DeviceCreateRequest.in = &get_DR_CREATE_REQ; + self->DeviceCreateRequest.__destructor = NULL; + self->out = &send_DR_DRIVE_CREATE_REQ; + self->in = &get_DR_DRIVE_CREATE_REQ; + self->__destructor = NULL; + + return rv; +} + +int APP_CC construct_DR_DRIVE_CLOSE_REQ(DR_DRIVE_CLOSE_REQ * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_CLOSE_REQ)); + construct_RDPDR_HEADER(&(self->DeviceCloseRequest.DeviceIoRequest.Header)); + construct_DR_DEVICE_IOREQUEST(&(self->DeviceCloseRequest.DeviceIoRequest)); + construct_DR_CLOSE_REQ(&(self->DeviceCloseRequest)); + self->out = &send_DR_DRIVE_CLOSE_REQ; + self->in = &get_DR_DRIVE_CLOSE_REQ; + + self->DeviceCloseRequest.DeviceIoRequest.MajorFunction = IRP_MJ_CLOSE; + + return rv; +} + +int APP_CC construct_DR_DRIVE_READ_REQ(DR_DRIVE_READ_REQ * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_READ_REQ)); + construct_RDPDR_HEADER(&(self->DeviceReadRequest.DeviceIoRequest.Header)); + construct_DR_DEVICE_IOREQUEST(&(self->DeviceReadRequest.DeviceIoRequest)); + construct_DR_READ_REQ(&(self->DeviceReadRequest)); + self->out = &send_DR_DRIVE_READ_REQ; + self->in = &get_DR_DRIVE_READ_REQ; + self->DeviceReadRequest.DeviceIoRequest.MajorFunction = IRP_MJ_READ; + + return rv; +} + +int APP_CC construct_DR_DRIVE_WRITE_REQ(DR_DRIVE_WRITE_REQ * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_WRITE_REQ)); + construct_RDPDR_HEADER(&(self->DeviceWriteRequest.DeviceIoRequest.Header)); + construct_DR_DEVICE_IOREQUEST(&(self->DeviceWriteRequest.DeviceIoRequest)); + construct_DR_WRITE_REQ(&(self->DeviceWriteRequest)); + self->out = &send_DR_DRIVE_WRITE_REQ; + self->in = &get_DR_DRIVE_WRITE_REQ; + + self->DeviceWriteRequest.DeviceIoRequest.MajorFunction = IRP_MJ_WRITE; + + return rv; +} + +int APP_CC construct_DR_DRIVE_CONTROL_REQ(DR_DRIVE_CONTROL_REQ * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_CONTROL_REQ)); + construct_RDPDR_HEADER(&(self->Header.DeviceIoRequest.Header)); + construct_DR_DEVICE_IOREQUEST(&(self->Header.DeviceIoRequest)); + construct_DR_CONTROL_REQ(&(self->Header)); + self->out = &send_DR_DRIVE_CONTROL_REQ; + self->in = &get_DR_DRIVE_CONTROL_REQ; + + self->Header.DeviceIoRequest.MajorFunction = IRP_MJ_DEVICE_CONTROL; + + return rv; +} + +int APP_CC construct_DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ(DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ)); + construct_RDPDR_HEADER(&(self->DeviceIoRequest.Header)); + construct_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest)); + self->DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + self->DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + self->DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + self->DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + self->in = &get_DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ; + self->out = &send_DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ; + self->__destructor = NULL; + self->DeviceIoRequest.Header.__destructor = NULL; + self->DeviceIoRequest.__destructor = NULL; + self->DeviceIoRequest.MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION; + self->FsInformationClass = FileFsVolumeInformation; + rv = sizeof(FILE_FS_VOLUME_INFORMATION) + (sizeof(char) * 128); + self->QueryVolumeBuffer.FsVolumeInformation = (FILE_FS_VOLUME_INFORMATION *)g_malloc(rv, 1); + self->Length = rv; + rv = 0; + + return rv; +} + +int APP_CC construct_DR_DRIVE_SET_VOLUME_INFORMATION_REQ(DR_DRIVE_SET_VOLUME_INFORMATION_REQ * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_SET_VOLUME_INFORMATION_REQ)); + construct_RDPDR_HEADER(&(self->DeviceIoRequest.Header)); + construct_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest)); + self->DeviceIoRequest.MajorFunction = IRP_MJ_SET_INFORMATION; + //self->DeviceIoRequest.MinorFunction = 0x00000000; + self->FsInformationClass = FileBasicInformation; + self->out = &send_DR_DRIVE_SET_VOLUME_INFORMATION_REQ; + self->in = &get_DR_DRIVE_SET_VOLUME_INFORMATION_REQ; + + return rv; +} + +int APP_CC construct_DR_DRIVE_QUERY_INFORMATION_REQ(DR_DRIVE_QUERY_INFORMATION_REQ * self) { + /* [MS-RDPEFS] @ 2.2.3.3.10 */ + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_QUERY_INFORMATION_REQ)); + construct_RDPDR_HEADER(&(self->DeviceIoRequest.Header)); + construct_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest)); + self->__destructor = NULL; + self->DeviceIoRequest.__destructor = NULL; + self->DeviceIoRequest.Header.__destructor = NULL; + self->DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + self->DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + self->out = &send_DR_DRIVE_QUERY_INFORMATION_REQ; + self->DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + self->DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + self->in = &get_DR_DRIVE_QUERY_INFORMATION_REQ; + self->DeviceIoRequest.MajorFunction = IRP_MJ_QUERY_INFORMATION; + self->DeviceIoRequest.MinorFunction = 0x00000000; + self->FsInformationClass = FileBasicInformation; + self->Length = 40; /* UTF-16 null terminator */ + + return rv; +} + +int APP_CC construct_DR_DRIVE_SET_INFORMATION_REQ(DR_DRIVE_SET_INFORMATION_REQ * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_SET_INFORMATION_REQ)); + construct_RDPDR_HEADER(&(self->DeviceIoRequest.Header)); + construct_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest)); + self->DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + self->DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + self->DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + self->DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + self->DeviceIoRequest.MajorFunction = IRP_MJ_SET_INFORMATION; + self->DeviceIoRequest.MinorFunction = 0x00000000; + self->FsInformationClass = FileBasicInformation; + self->out = &send_DR_DRIVE_SET_INFORMATION_REQ; + self->in = &get_DR_DRIVE_SET_INFORMATION_REQ; + + return rv; +} + +int APP_CC construct_RDP_FILE_RENAME_INFORMATION(RDP_FILE_RENAME_INFORMATION * self) { + int rv = 0; + + g_memset(self,0,sizeof(RDP_FILE_RENAME_INFORMATION)); + + return rv; +} + +int APP_CC construct_DR_DRIVE_QUERY_DIRECTORY_REQ(DR_DRIVE_QUERY_DIRECTORY_REQ * self) { + int rv = 0; + + if (self != NULL) { + g_memset(self,0,sizeof(DR_DRIVE_QUERY_DIRECTORY_REQ)); + construct_RDPDR_HEADER(&(self->DeviceIoRequest.Header)); + construct_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest)); + self->DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + self->DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + self->DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + self->DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + self->in = &get_DR_DRIVE_QUERY_DIRECTORY_REQ; + self->out = &send_DR_DRIVE_QUERY_DIRECTORY_REQ; + self->setPath = &setPath_DR_DRIVE_QUERY_DIRECTORY_REQ; + self->DeviceIoRequest.MajorFunction = IRP_MJ_DIRECTORY_CONTROL; + self->DeviceIoRequest.MinorFunction = IRP_MN_QUERY_DIRECTORY; + self->DeviceIoRequest.DeviceId = 0; + self->DeviceIoRequest.FileId = 0x00000001; + self->DeviceIoRequest.CompletionId = 0x00000000; + self->FsInformationClass = FileBothDirectoryInformation; + self->PathLength = 0x00000002; + self->InitialQuery = 0x01; + self->DeviceIoRequest.MajorFunction = IRP_MJ_DIRECTORY_CONTROL; + self->DeviceIoRequest.MinorFunction = IRP_MN_QUERY_DIRECTORY; + self->DeviceIoRequest.Header.__destructor = NULL; + self->DeviceIoRequest.__destructor = NULL; + self->__destructor = NULL; + } + else { + rv = -1; + } + + return rv; +} + +int APP_CC construct_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ)); + construct_RDPDR_HEADER(&(self->DeviceIoRequest.Header)); + construct_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest)); + self->DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + self->DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + self->DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + self->DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + + self->DeviceIoRequest.MajorFunction = IRP_MJ_DIRECTORY_CONTROL; + self->DeviceIoRequest.MinorFunction = IRP_MN_NOTIFY_CHANGE_DIRECTORY; + self->WatchTree = 0x00; + self->CompletionFilter = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_CREATION; + self->in = &get_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ; + self->out = &send_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ; + + return rv; +} + +int APP_CC construct_DR_DRIVE_LOCK_REQ(DR_DRIVE_LOCK_REQ * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_LOCK_REQ)); + construct_RDPDR_HEADER(&(self->DeviceIoRequest.Header)); + construct_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest)); + self->out = &send_DR_DRIVE_LOCK_REQ; + self->in = &get_DR_DRIVE_LOCK_REQ; + + return rv; +} + +int APP_CC construct_DR_DRIVE_CORE_DEVICE_IOCOMPLETION(DR_DRIVE_CORE_DEVICE_IOCOMPLETION * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_CORE_DEVICE_IOCOMPLETION)); + construct_RDPDR_HEADER(&(self->DeviceIoResponse.Header)); + construct_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoResponse)); + self->DeviceIoResponse.Header.out = &send_RDPDR_HEADER; + self->DeviceIoResponse.Header.in = &get_RDPDR_HEADER; + self->DeviceIoResponse.Header.__destructor = NULL; + self->DeviceIoResponse.__destructor = NULL; + self->DeviceIoResponse.out = &send_DR_DEVICE_IOCOMPLETION; + self->DeviceIoResponse.in = &get_DR_DEVICE_IOCOMPLETION; + self->out = &send_DR_DRIVE_CORE_DEVICE_IOCOMPLETION; + self->in = &get_DR_DRIVE_CORE_DEVICE_IOCOMPLETION; + self->__destructor = NULL; + + return rv; +} + +int APP_CC construct_DR_DRIVE_CREATE_RSP(DR_DRIVE_CREATE_RSP * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_CREATE_RSP)); + construct_RDPDR_HEADER(&(self->DeviceCreateResponse.DeviceIoReply.Header)); + construct_DR_DEVICE_IOCOMPLETION(&(self->DeviceCreateResponse.DeviceIoReply)); + construct_DR_CREATE_RSP(&(self->DeviceCreateResponse)); + self->DeviceCreateResponse.DeviceIoReply.Header.out = &send_RDPDR_HEADER; + self->DeviceCreateResponse.DeviceIoReply.Header.in = &get_RDPDR_HEADER; + self->DeviceCreateResponse.DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + self->DeviceCreateResponse.DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + self->DeviceCreateResponse.out = &send_DR_CREATE_RSP; + self->DeviceCreateResponse.in = &get_DR_CREATE_RSP; + self->out = &send_DR_DRIVE_CREATE_RSP; + self->in = &get_DR_DRIVE_CREATE_RSP; + + return rv; +} + +int APP_CC construct_DR_DRIVE_CLOSE_RSP(DR_DRIVE_CLOSE_RSP * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_CLOSE_RSP)); + construct_DR_CLOSE_RSP(&(self->DeviceCloseResponse)); + self->DeviceCloseResponse.out = &send_DR_CLOSE_RSP; + self->DeviceCloseResponse.in = &get_DR_CLOSE_RSP; + self->out = &send_DR_DRIVE_CLOSE_RSP; + self->in = &get_DR_DRIVE_CLOSE_RSP; + + return rv; +} + +int APP_CC construct_DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP(DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP)); + construct_RDPDR_HEADER(&(self->DeviceIoReply.Header)); + construct_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply)); + self->DeviceIoReply.Header.in = &get_RDPDR_HEADER; + self->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + self->DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + self->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + self->in = &get_DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP; + self->out = &send_DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP; + + return rv; +} + +int APP_CC construct_DR_DRIVE_SET_VOLUME_INFORMATION_RSP(DR_DRIVE_SET_VOLUME_INFORMATION_RSP * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_SET_VOLUME_INFORMATION_RSP)); + construct_RDPDR_HEADER(&(self->DeviceIoReply.Header)); + construct_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply)); + self->DeviceIoReply.Header.in = &get_RDPDR_HEADER; + self->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + self->DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + self->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + self->out = &send_DR_DRIVE_SET_VOLUME_INFORMATION_RSP; + self->in = &get_DR_DRIVE_SET_VOLUME_INFORMATION_RSP; + + return rv; +} + +int APP_CC construct_DR_DRIVE_QUERY_INFORMATION_RSP(DR_DRIVE_QUERY_INFORMATION_RSP * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_QUERY_INFORMATION_RSP)); + construct_RDPDR_HEADER(&(self->DeviceIoReply.Header)); + construct_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply)); + self->DeviceIoReply.Header.in = &get_RDPDR_HEADER; + self->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + self->DeviceIoReply.Header.__destructor = NULL; + self->DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + self->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + self->DeviceIoReply.__destructor = NULL; + self->in = &get_DR_DRIVE_QUERY_INFORMATION_RSP; + self->out = &send_DR_DRIVE_QUERY_INFORMATION_RSP; + self->__destructor = NULL; + + return rv; +} + +int APP_CC construct_DR_DRIVE_QUERY_DIRECTORY_RSP(DR_DRIVE_QUERY_DIRECTORY_RSP * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_QUERY_DIRECTORY_RSP)); + construct_RDPDR_HEADER(&(self->DeviceIoReply.Header)); + construct_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply)); + self->DeviceIoReply.Header.in = &get_RDPDR_HEADER; + self->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + self->DeviceIoReply.Header.__destructor = NULL; + self->DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + self->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + self->DeviceIoReply.__destructor = NULL; + self->in = &get_DR_DRIVE_QUERY_DIRECTORY_RSP; + self->out = &send_DR_DRIVE_QUERY_DIRECTORY_RSP; + self->__destructor = NULL; + + return rv; +} + +int APP_CC construct_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP)); + construct_RDPDR_HEADER(&(self->DeviceIoReply.Header)); + construct_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply)); + self->DeviceIoReply.Header.in = &get_RDPDR_HEADER; + self->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + self->DeviceIoReply.Header.__destructor = NULL; + self->DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + self->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + self->DeviceIoReply.__destructor = NULL; + self->in = &get_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP; + self->out = &send_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP; + self->__destructor = NULL; + + return rv; +} + +int APP_CC construct_DR_DRIVE_LOCK_RSP(DR_DRIVE_LOCK_RSP * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_LOCK_RSP)); + construct_RDPDR_HEADER(&(self->DeviceIoReply.Header)); + construct_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply)); + self->DeviceIoReply.Header.in = &get_RDPDR_HEADER; + self->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + self->DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + self->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + self->in = &get_DR_DRIVE_LOCK_RSP; + self->out = &send_DR_DRIVE_LOCK_RSP; + + return rv; +} + +int APP_CC construct_DR_CORE_USER_LOGGEDON(DR_CORE_USER_LOGGEDON * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_CORE_USER_LOGGEDON)); + construct_RDPDR_HEADER(&(self->Header)); + self->Header.in = &get_RDPDR_HEADER; + self->Header.out = &send_RDPDR_HEADER; + self->in = &get_DR_CORE_USER_LOGGEDON; + self->out = &send_DR_CORE_USER_LOGGEDON; + self->Header.Component = RDPDR_CTYP_CORE; + self->Header.PacketId = PAKID_CORE_USER_LOGGEDON; + + return rv; +} + +int APP_CC construct_DR_DRIVE_SET_INFORMATION_RSP(DR_DRIVE_SET_INFORMATION_RSP * self) { + int rv = 0; + + g_memset(self,0,sizeof(DR_DRIVE_SET_INFORMATION_RSP)); + construct_RDPDR_HEADER(&(self->DeviceIoReply.Header)); + construct_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply)); + self->DeviceIoReply.Header.in = &get_RDPDR_HEADER; + self->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + self->DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + self->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + self->out = &send_DR_DRIVE_SET_INFORMATION_RSP; + self->in = &get_DR_DRIVE_SET_INFORMATION_RSP; + + return rv; +} + +int APP_CC construct_DYNVC_CAPS_VERSION2(DYNVC_CAPS_VERSION2 * self) { + int rv = 0; + uint8_t hdr = 0x00; + uint8_t cmd = 0x00; + uint8_t sp = 0x00; + uint8_t cb = 0x00; + + if (self == NULL) { + rv = -1; + goto end; + } + + cmd = DRDYNVC_CAPABILITIES; + sp = 0x00; + cb = 0x00; + hdr = (cmd << 4) | (sp << 2) | (cb); + + g_memset(self, 0x00, sizeof(DYNVC_CAPS_VERSION2)); + self->Cmd = DRDYNVC_CAPABILITIES; + self->Sp = 0x00; + self->cbChId = DRDYNVC_NONE; + self->Pad = 0x00; + self->Version = DRDYNVC_VERSION2; + self->PriorityCharge0 = 0x00000000; + self->PriorityCharge1 = 0x00000000; + self->PriorityCharge2 = 0x00000000; + self->PriorityCharge3 = 0x00000000; + self->in = &get_DYNVC_CAPS_VERSION2; + self->out = &send_DYNVC_CAPS_VERSION2; + self->destroy = &destroy_DYNVC_CAPS_VERSION2; + + end:; + return rv; +} + +int APP_CC construct_DYNVC_CAPS_VERSION1(DYNVC_CAPS_VERSION1 * self) { + int rv = 0; + + if (self == NULL) { + rv = -1; + goto end; + } + + g_memset(self, 0x00, sizeof(DYNVC_CAPS_VERSION1)); + self->Cmd = DRDYNVC_CAPABILITIES; + self->Sp = 0x02; + self->cbChId = DRDYNVC_NONE; + self->Pad = 0x00; + self->Version = DRDYNVC_VERSION1; + self->in = &get_DYNVC_CAPS_VERSION1; + self->out = &send_DYNVC_CAPS_VERSION1; + self->destroy = &destroy_DYNVC_CAPS_VERSION1; + + end:; + return rv; +} + +int APP_CC construct_DYNVC_CAPS_RSP(DYNVC_CAPS_RSP * self) { + int rv = 0; + + if (self == NULL) { + rv = -1; + goto end; + } + + g_memset(self, 0x00, sizeof(DYNVC_CAPS_VERSION1)); + self->Cmd = DRDYNVC_CAPABILITIES; + self->Sp = 0x02; + self->cbChId = DRDYNVC_NONE; + self->Pad = 0x00; + self->Version = DRDYNVC_VERSION2; + self->in = &get_DYNVC_CAPS_RSP; + self->out = &send_DYNVC_CAPS_RSP; + self->destroy = &destroy_DYNVC_CAPS_RSP; + + end:; + return rv; +} + +int APP_CC construct_DYNVC_CREATE_REQ(DYNVC_CREATE_REQ * self) { + int rv = 0; + + if (self == NULL) { + rv = -1; + goto end; + } + + g_memset(self, 0x00, sizeof(DYNVC_CREATE_REQ)); + self->Cmd = DRDYNVC_CREATE; + self->Pri = 0x00; + self->cbChId = DRDYNVC_BYTE; + self->in = &get_DYNVC_CREATE_REQ; + self->out = &send_DYNVC_CREATE_REQ; + self->destroy = &destroy_DYNVC_CREATE_REQ; + + end:; + return rv; +} + +int APP_CC construct_DYNVC_CREATE_RSP(DYNVC_CREATE_RSP * self) { + int rv = 0; + + if (self == NULL) { + rv = -1; + goto end; + } + + g_memset(self, 0x00, sizeof(DYNVC_CREATE_RSP)); + self->Cmd = DRDYNVC_CREATE; + self->in = &get_DYNVC_CREATE_RSP; + self->out = &send_DYNVC_CREATE_RSP; + self->destroy = &destroy_DYNVC_CREATE_RSP; + + end:; + return rv; +} + +int APP_CC construct_DYNVC_DATA_FIRST(DYNVC_DATA_FIRST * self) { + int rv = 0; + + if (self == NULL) { + rv = -1; + goto end; + } + + g_memset(self, 0x00, sizeof(DYNVC_DATA_FIRST)); + + self->Cmd = DRDYNVC_DATAFIRST; + self->Len = DRDYNVC_WORD; + self->cbChId = DRDYNVC_BYTE; + self->ChannelId = 0x01; + self->in = &get_DYNVC_DATA_FIRST; + self->out = &send_DYNVC_DATA_FIRST; + self->destroy = &destroy_DYNVC_DATA_FIRST; + + end:; + return rv; +} + +int APP_CC construct_DYNVC_DATA(DYNVC_DATA * self) { + int rv = 0; + + if (self == NULL) { + rv = -1; + goto end; + } + + g_memset(self, 0x00, sizeof(DYNVC_DATA)); + self->Cmd = DRDYNVC_DATA; + self->Sp = DRDYNVC_NONE; + self->cbChId = DRDYNVC_BYTE; + self->in = &get_DYNVC_DATA; + self->out = &send_DYNVC_DATA; + self->destroy = &destroy_DYNVC_DATA; + + end:; + return rv; +} + +int APP_CC construct_DYNVC_CLOSE(DYNVC_CLOSE * self) { + int rv = 0; + + if (self == NULL) { + rv = -1; + goto end; + } + + g_memset(self, 0x00, sizeof(DYNVC_CLOSE)); + self->Cmd = DRDYNVC_CLOSE; + self->Sp = DRDYNVC_NONE; + self->cbChId = DRDYNVC_BYTE; + self->in = &get_DYNVC_CLOSE; + self->out = &send_DYNVC_CLOSE; + self->destroy = &destroy_DYNVC_CLOSE; + + end:; + return rv; +} + + +int APP_CC construct_MSG_SNDIN_VERSION(MSG_SNDIN_VERSION * self) { + int rv = 0; + + if (self == NULL) { + rv = -1; + goto end; + } + + self->Header.MessageId = CMSG_SNDIN_VERSION; + self->Version = SNDIN_VERSION; + + end:; + return rv; +} + +int APP_CC construct_MSG_SNDIN_FORMATS(MSG_SNDIN_FORMATS * self) { + int rv = 0; + + if (self == NULL) { + rv = -1; + goto end; + } + + self->Header.MessageId = CMSG_SNDIN_FORMATS; + self->cbSizeFormatsPacket = 0x80000000; + + end:; + return rv; +} + +int APP_CC construct_MSG_SNDIN_OPEN(MSG_SNDIN_OPEN * self) { + int rv = 0; + WAVEFORMAT_EXTENSIBLE * buf = (WAVEFORMAT_EXTENSIBLE *)NULL; + const GUID tguid = KSDATAFORMAT_SUBTYPE_PCM; + + if (self == NULL) { + rv = -1; + goto end; + } + + self->initialFormat = 0x00000001; + self->FramesPerPacket = 0x00000000; + self->Header.MessageId = CMSG_SNDIN_OPEN; + self->wFormatTag = WAVE_FORMAT_EXTENSIBLE; + self->cbSize = sizeof(GUID); + buf = (WAVEFORMAT_EXTENSIBLE *)(self->ExtraFormatData); + g_memcpy(&(buf->SubFormat),&tguid,sizeof(GUID)); + self->nChannels = 0x02; + self->nSamplesPerSec = 0x00000000; + self->nAvgBytesPerSec = 0x00000000; + self->nBlockAlign = 0x0000; + self->wBitsPerSample = 0x00000000; + + end:; + return rv; +} + +int APP_CC construct_WAVEFORMAT_EXTENSIBLE(WAVEFORMAT_EXTENSIBLE * self) { + int rv = 0; + const GUID tguid = KSDATAFORMAT_SUBTYPE_PCM; + + if (self == NULL) { + rv = -1; + goto end; + } + + g_memcpy(&(self->SubFormat), &tguid, sizeof(GUID)); + + end:; + return rv; +} + +int APP_CC construct_MSG_SNDIN_OPEN_REPLY(MSG_SNDIN_OPEN_REPLY * self) { + int rv = 0; + + if (self == NULL) { + rv = -1; + goto end; + } + + self->Header.MessageId = CMSG_SNDIN_OPEN_REPLY; + + end:; + return rv; +} + +int APP_CC construct_MSG_SNDIN_DATA_INCOMING(MSG_SNDIN_DATA_INCOMING * self) { + int rv = 0; + + if (self == NULL) { + rv = -1; + goto end; + } + + self->Header.MessageId = CMSG_SNDIN_DATA_INCOMING; + + end:; + return rv; +} + +int APP_CC construct_MSG_SNDIN_DATA(MSG_SNDIN_DATA * self) { + int rv = 0; + + if (self == NULL) { + rv = -1; + goto end; + } + + self->Header.MessageId = CMSG_SNDIN_DATA; + + end:; + return rv; +} + +int APP_CC construct_MSG_SNDIN_FORMATCHANGE(MSG_SNDIN_FORMATCHANGE * self) { + int rv = 0; + + if (self == NULL) { + rv = -1; + goto end; + } + + self->Header.MessageId = CMSG_SNDIN_FORMATCHANGE; + + end:; + return rv; +} + +/* +int APP_CC construct_( * self) { + int rv = 0; + return rv; +} +*/ + +/********************************************************************** + * END: CONSTRUCTORS + **********************************************************************/ + + +/********************************************************************** + * BEGIN: SENDERS / GETTERS + **********************************************************************/ + +int APP_CC send_DR_CORE_SERVER_ANNOUNCE_REQ(DR_CORE_SERVER_ANNOUNCE_REQ * self, struct stream * s) { + int rv = 0; + + send_RDPDR_HEADER(&(self->Header), s); + out_uint16_le(s, self->VersionMajor); + out_uint16_le(s, self->VersionMinor); + out_uint32_le(s, self->ClientId); + + return rv; +} + +int APP_CC send_RDPDR_HEADER(RDPDR_HEADER * self, struct stream * s) { + int rv = 0; + + if (self == NULL || s == NULL) { + // MDBGLOG("redir","send_RDPDR_HEADER(): empty self or null stream"); + rv = -1; + } + else { + out_uint16_le(s, self->Component); + out_uint16_le(s, self->PacketId); + } + + return rv; +} + +int APP_CC get_RDPDR_HEADER(RDPDR_HEADER * self, struct stream * s) { + int rv = 0; + + if (self == NULL || s == NULL) { + // MDBGLOG("redir","get_RDPDR_HEADER(): empty self or null stream"); + rv = -1; + } + else { + in_uint16_le(s, self->Component); + in_uint16_le(s, self->PacketId); + } + + return rv; +} + +int APP_CC get_DR_CORE_SERVER_ANNOUNCE_RSP(DR_CORE_SERVER_ANNOUNCE_RSP * self, struct stream * s) { + int rv = 0; + + get_RDPDR_HEADER(&(self->Header), s); + in_uint16_le(s, self->VersionMajor); + in_uint16_le(s, self->VersionMinor); + in_uint32_le(s, self->ClientId); + + return rv; +} + +int APP_CC get_DR_CORE_CLIENT_NAME_REQ(DR_CORE_CLIENT_NAME_REQ * self, struct stream * s) { + int rv = 0; + + get_RDPDR_HEADER(&(self->Header), s); + in_uint32_le(s, self->UnicodeFlag); + in_uint32_le(s, self->CodePage); + in_uint32_le(s, self->ComputerNameLen); + if (self->ComputerNameLen > 0) { + self->ComputerName = (BYTE *)g_malloc(sizeof(BYTE) * self->ComputerNameLen,1); + in_uint8a(s, self->ComputerName, self->ComputerNameLen); + } + + return rv; +} + +int APP_CC send_DR_CORE_USER_LOGGEDON(DR_CORE_USER_LOGGEDON * self, struct stream * s) { + int rv = 0; + + send_RDPDR_HEADER(&(self->Header), s); + + return rv; +} + +int APP_CC +get_DR_CORE_USER_LOGGEDON(DR_CORE_USER_LOGGEDON * self, struct stream * s) { + int rv = 0; + + get_RDPDR_HEADER(&(self->Header), s); + + return rv; +} + +int APP_CC send_CAPABILITY_HEADER(CAPABILITY_HEADER * self, struct stream * s) { + int rv = 0; + + out_uint16_le(s, self->CapabilityType); + out_uint16_le(s, self->CapabilityLength); + out_uint32_le(s, self->Version); + + return rv; +} + +int APP_CC get_CAPABILITY_HEADER(CAPABILITY_HEADER * self, struct stream * s) { + int rv = 0; + + in_uint16_le(s, self->CapabilityType); + in_uint16_le(s, self->CapabilityLength); + in_uint32_le(s, self->Version); + + return rv; +} + +int APP_CC +send_DR_DEVICE_IOREQUEST(DR_DEVICE_IOREQUEST * self, struct stream * s) { + int rv = 0; + + send_RDPDR_HEADER(&(self->Header), s); + out_uint32_le(s, self->DeviceId); + out_uint32_le(s, self->FileId); + out_uint32_le(s, self->CompletionId); + out_uint32_le(s, self->MajorFunction); + out_uint32_le(s, self->MinorFunction); + + return rv; +} + +int APP_CC +get_DR_DEVICE_IOREQUEST(DR_DEVICE_IOREQUEST * self, struct stream * s) { + int rv = 0; + + get_RDPDR_HEADER(&(self->Header), s); + in_uint32_le(s, self->DeviceId); + in_uint32_le(s, self->FileId); + in_uint32_le(s, self->CompletionId); + in_uint32_le(s, self->MajorFunction); + in_uint32_le(s, self->MinorFunction); + + return rv; +} + +int APP_CC send_DR_CREATE_REQ(DR_CREATE_REQ * self, struct stream * s) { + int rv = 0; + int idx = 0; + + // MDBGLOG("redir","INFO\t[%s()]: called [%d, %d]",__func__,g_getpid(),g_gettid()); + send_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + out_uint32_le(s, self->DesiredAccess); + out_uint64_le(s, self->AllocationSize); + out_uint32_le(s, self->FileAttributes); + out_uint32_le(s, self->SharedAccess); + out_uint32_le(s, self->CreateDisposition); + out_uint32_le(s, self->CreateOptions); + out_uint32_le(s, self->PathLength); + if (self->PathLength > 0 && self->Path != NULL) { + for (idx = 0; idx < self->PathLength; idx++) { + out_uint8(s, self->Path[idx]); + } + } + else if (self->PathLength > 0) { + //out_uint8(s, 0x00); + } + // MDBGLOG("redir","INFO\t[%s()]: done.",__func__); + + return rv; +} + +int APP_CC +get_DR_CREATE_REQ(DR_CREATE_REQ * self, struct stream * s) { + int rv = 0; + int idx = 0; + + get_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + in_uint32_le(s, self->DesiredAccess); + in_uint64_le(s, self->AllocationSize); + in_uint32_le(s, self->FileAttributes); + in_uint32_le(s, self->SharedAccess); + in_uint32_le(s, self->CreateDisposition); + in_uint32_le(s, self->CreateOptions); + in_uint32_le(s, self->PathLength); + for (idx = 0; idx < self->PathLength; idx++) { + in_uint8(s, self->Path[idx]); + } + + return rv; +} + +int APP_CC +send_DR_DRIVE_CREATE_REQ(DR_DRIVE_CREATE_REQ * self, struct stream * s) { + int rv = 0; + + send_DR_CREATE_REQ(&(self->DeviceCreateRequest), s); + + return rv; +} + +int APP_CC +get_DR_DRIVE_CREATE_REQ(DR_DRIVE_CREATE_REQ * self, struct stream * s) { + int rv = 0; + + get_DR_CREATE_REQ(&(self->DeviceCreateRequest), s); + + return rv; +} + +int APP_CC +send_DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ(DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + out_uint32_le(s, self->FsInformationClass); + out_uint32_le(s, self->Length); + out_uint8a(s, self->Padding, 24); + if (self->Length > 0) { + out_uint8a(s, self->QueryVolumeBuffer.bytes, self->Length); + } + + return rv; +} + +int APP_CC +get_DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ(DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + in_uint32_le(s, self->FsInformationClass); + in_uint32_le(s, self->Length); + in_uint8a(s, self->Padding, 24); + if (self->Length > 0) { + self->QueryVolumeBuffer.bytes = (BYTE *)g_malloc(sizeof(BYTE), 1); + in_uint8a(s, &(self->QueryVolumeBuffer.bytes), self->Length); + } + + return rv; +} + +int APP_CC +send_DR_DRIVE_QUERY_DIRECTORY_REQ(DR_DRIVE_QUERY_DIRECTORY_REQ * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + out_uint32_le(s, self->FsInformationClass); + out_uint8(s, self->InitialQuery); + out_uint32_le(s, self->PathLength); + out_uint8a(s, self->Padding, 23); + if (self->PathLength > 0) { + out_uint8a(s, self->Path, self->PathLength); + } + + return rv; +} + +int APP_CC +get_DR_DRIVE_QUERY_DIRECTORY_REQ(DR_DRIVE_QUERY_DIRECTORY_REQ * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + in_uint32_le(s, self->FsInformationClass); + in_uint8(s, self->InitialQuery); + in_uint32_le(s, self->PathLength); + in_uint8a(s, self->Padding, 23); + if (self->PathLength > 0) { + in_uint8a(s, self->Path, self->PathLength); + } + + return rv; +} + +int APP_CC +send_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + out_uint8(s, self->WatchTree); + out_uint32_le(s, self->CompletionFilter); + out_uint8s(s, 27); + + return rv; +} + +int APP_CC +get_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + in_uint8(s, self->WatchTree); + in_uint32_le(s, self->CompletionFilter); + in_uint8s(s, 27); + + return rv; +} + +int APP_CC +send_DR_DEVICE_IOCOMPLETION(DR_DEVICE_IOCOMPLETION * self, struct stream * s) { + int rv = 0; + + send_RDPDR_HEADER(&(self->Header), s); + out_uint32_le(s, self->DeviceId); + out_uint32_le(s, self->CompletionId); + out_uint32_le(s, self->IoStatus.Value); + + return rv; +} + +int APP_CC +get_DR_DEVICE_IOCOMPLETION(DR_DEVICE_IOCOMPLETION * self, struct stream * s) { + int rv = 0; + + get_RDPDR_HEADER(&(self->Header), s); + in_uint32_le(s, self->DeviceId); + in_uint32_le(s, self->CompletionId); + in_uint32_le(s, self->IoStatus.Value); + + return rv; +} + +int APP_CC +send_DR_DRIVE_QUERY_DIRECTORY_RSP(DR_DRIVE_QUERY_DIRECTORY_RSP * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + out_uint32_le(s, self->Length); + if (self->Length > 0) { + out_uint8a(s, self->Buffer.bytes, self->Length); + } + //out_uint8(s, self->Padding); + + return rv; +} + +int APP_CC +get_DR_DRIVE_QUERY_DIRECTORY_RSP(DR_DRIVE_QUERY_DIRECTORY_RSP * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + in_uint32_le(s, self->Length); + if (self->Length > 0) { + in_uint8a(s, self->Buffer.bytes, self->Length); + } + in_uint8(s, self->Padding); + + return rv; +} + +int APP_CC get_FILE_NAME_INFORMATION(FILE_NAME_INFORMATION * self, struct stream * s) { + int rv = 0; + + g_memset(self->FileName,0,sizeof(BYTE)*1024); + in_uint32_le(s, self->FileNameLength); + if (self->FileNameLength > 0) { + in_uint8a(s, (char *)self->FileName, self->FileNameLength); + } + + return rv; +} + +int APP_CC get_FILE_BASIC_INFORMATION(FILE_BASIC_INFORMATION * self, struct stream * s) { + int rv = 0; + + in_uint64_le(s, self->CreationTime); + in_uint64_le(s, self->LastAccessTime); + in_uint64_le(s, self->LastWriteTime); + in_uint64_le(s, self->ChangeTime); + in_uint32_le(s, self->FileAttributes); + in_uint32_le(s, self->Reserved); + + return rv; +} + +int APP_CC get_FILE_STANDARD_INFORMATION(FILE_STANDARD_INFORMATION * self, struct stream * s) { + int rv = 0; + + in_uint64_le(s, self->AllocationSize); + in_uint64_le(s, self->EndOfFile); + in_uint32_le(s, self->NumberOfLinks); + in_uint8(s, self->DeletePending); + in_uint8(s, self->Directory); + in_uint16_le(s, self->Reserved); + + return rv; +} + +int APP_CC get_FILE_ALL_INFORMATION(FILE_ALL_INFORMATION * self, struct stream * s) { + int rv = 0; + + get_FILE_BASIC_INFORMATION(&(self->BasicInformation), s); + get_FILE_STANDARD_INFORMATION(&(self->StandardInformation), s); + in_uint64_le(s, self->InternalInformation); + in_uint32_le(s, self->EaInformation); + in_uint32_le(s, self->AccessInformation); + in_uint64_le(s, self->PositionInformation); + in_uint32_le(s, self->ModeInformation); + in_uint32_le(s, self->AlignmentInformation); + get_FILE_NAME_INFORMATION(&(self->NameInformation), s); + + return rv; +} + +int APP_CC get_FILE_BOTH_DIR_INFORMATION(FILE_BOTH_DIR_INFORMATION * self, struct stream * s) { + int rv = 0; + + in_uint32_le(s, self->NextEntryOffset); + in_uint32_le(s, self->FileIndex); + in_uint64_le(s, self->CreationTime); + in_uint64_le(s, self->LastAccessTime); + in_uint64_le(s, self->LastWriteTime); + in_uint64_le(s, self->ChangeTime); + in_uint64_le(s, self->EndOfFile); + in_uint64_le(s, self->AllocationSize); + in_uint32_le(s, self->FileAttributes); + in_uint32_le(s, self->FileNameLength); + in_uint32_le(s, self->EaSize); + in_uint8(s, self->ShortNameLength); + //in_uint8(s, self->Reserved); + in_uint8a(s, self->ShortName, 24); + if (self->FileNameLength > 0) { + in_uint8a(s, (char *)(self->FileName), self->FileNameLength); + } + + return rv; +} + +int APP_CC send_FILE_NAME_INFORMATION(FILE_NAME_INFORMATION * self, struct stream * s) { + int rv = 0; + + out_uint32_le(s, self->FileNameLength); + if (self->FileNameLength > 0) { + out_uint8a(s, (char *)self->FileName, self->FileNameLength); + } + + return rv; +} + +int APP_CC send_FILE_BASIC_INFORMATION(FILE_BASIC_INFORMATION * self, struct stream * s) { + int rv = 0; + + out_uint64_le(s, self->CreationTime); + out_uint64_le(s, self->LastAccessTime); + out_uint64_le(s, self->LastWriteTime); + out_uint64_le(s, self->ChangeTime); + out_uint32_le(s, self->FileAttributes); + out_uint32_le(s, self->Reserved); + + return rv; +} + +int APP_CC send_FILE_STANDARD_INFORMATION(FILE_STANDARD_INFORMATION * self, struct stream * s) { + int rv = 0; + + out_uint64_le(s, self->AllocationSize); + out_uint64_le(s, self->EndOfFile); + out_uint32_le(s, self->NumberOfLinks); + out_uint8(s, self->DeletePending); + out_uint8(s, self->Directory); + out_uint16_le(s, self->Reserved); + + return rv; +} + +int APP_CC send_FILE_BOTH_DIR_INFORMATION(FILE_BOTH_DIR_INFORMATION * self, struct stream * s) { + int rv = 0; + char buf[512]; + g_memset(buf,0,512); + + out_uint32_le(s, self->NextEntryOffset); + out_uint32_le(s, self->FileIndex); + out_uint64_le(s, self->CreationTime); + out_uint64_le(s, self->LastAccessTime); + out_uint64_le(s, self->LastWriteTime); + out_uint64_le(s, self->ChangeTime); + out_uint64_le(s, self->EndOfFile); + out_uint64_le(s, self->AllocationSize); + out_uint32_le(s, self->FileAttributes); + out_uint32_le(s, self->FileNameLength); + out_uint32_le(s, self->EaSize); + out_uint8(s, self->ShortNameLength); + //out_uint8(s, self->Reserved); + out_uint8a(s, self->ShortName, 24); + if (self->FileNameLength > 0) { + out_uint8a(s, (char *)(self->FileName), self->FileNameLength); + } + + if (1==2) { + // MDBGLOG("redir"," ----------- "); + // MDBGLOG("redir"," * NextEntryOffset = %u",self->NextEntryOffset); + // MDBGLOG("redir"," * FileIndex = %u",self->FileIndex); + // MDBGLOG("redir"," * CreationTime = %lu",self->CreationTime); + // MDBGLOG("redir"," * LastAccessTime = %lu",self->LastAccessTime); + // MDBGLOG("redir"," * LastWriteTime = %lu",self->LastWriteTime); + // MDBGLOG("redir"," * ChangeTime = %lu",self->ChangeTime); + // MDBGLOG("redir"," * EndOfFile = %lu",self->EndOfFile); + // MDBGLOG("redir"," * AllocationSize = %lu",self->AllocationSize); + // MDBGLOG("redir"," * FileAttributes = 0x%8.8x",self->FileAttributes); + // MDBGLOG("redir"," * FileNameLength = %u",self->FileNameLength); + // MDBGLOG("redir"," * EaSize = %u",self->EaSize); + // MDBGLOG("redir"," * ShortNameLength = %u",self->ShortNameLength); + //// MDBGLOG("redir"," * Reserved = %u",self->Reserved); + for (rv=0;rv<((self->ShortNameLength > 23) ? 23 : self->ShortNameLength);rv++) { + buf[rv] = self->ShortName[(rv * 2)]; + } + //g_snprintf(buf,((self->ShortNameLength > 23) ? 23 : self->ShortNameLength),"%s",self->ShortName); + // MDBGLOG("redir"," * ShortName = %s\n", buf); + g_memset(buf,0,512); + for (rv=0;rv<((self->FileNameLength > 510) ? 510 : self->FileNameLength);rv++) { + buf[rv] = self->FileName[(rv * 2)]; + } + //g_snprintf(buf,((self->FileNameLength > 510) ? 510 : self->FileNameLength),"%s",self->FileName); + // MDBGLOG("redir"," * FileName = %s\n", buf); + g_memset(buf,0,512); + rv = 0; + } + + return rv; +} + +/***/ +int APP_CC +get_CAPABILITY_SET(CAPABILITY_SET * self, struct stream * s) { + int rv = 0; + + get_CAPABILITY_HEADER(&(self->Header), s); + if (self->Header.CapabilityLength > 0) { + self->capabilityData = (BYTE *)g_malloc(sizeof(BYTE) * self->Header.CapabilityLength, 1); + in_uint8a(s, self->capabilityData, self->Header.CapabilityLength); + } + + return rv; +} + + +/***/ +int APP_CC +get_DEVICE_ANNOUNCE(DEVICE_ANNOUNCE * self, struct stream * s) { + int rv = 0; + + in_uint32_le(s, self->DeviceType); + in_uint32_le(s, self->DeviceId); + in_uint8a(s, self->PreferredDosName, 8); + in_uint32_le(s, self->DeviceDataLength); + if (self->DeviceDataLength > 0) { + self->DeviceData = (BYTE *)g_malloc(sizeof(BYTE) * self->DeviceDataLength, 1); + in_uint8a(s, self->DeviceData, self->DeviceDataLength); + } + + return rv; +} + + + +/***/ +int APP_CC +get_DR_CLOSE_REQ(DR_CLOSE_REQ * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + in_uint8a(s, self->Padding, 32); + + return rv; +} + + + +/***/ +int APP_CC +get_DR_READ_REQ(DR_READ_REQ * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + in_uint32_le(s, self->Length); + in_uint64_le(s, self->Offset); + in_uint8a(s, self->Padding, 20); + + return rv; +} + + + +/***/ +int APP_CC +get_DR_WRITE_REQ(DR_WRITE_REQ * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + in_uint32_le(s, self->Length); + in_uint64_le(s, self->Offset); + in_uint8a(s, self->Padding, 20); + if (self->Length > 0) { + self->WriteData = (BYTE *)g_malloc(sizeof(BYTE) * self->Length, 1); + in_uint8a(s, self->WriteData, self->Length); + } + + return rv; +} + + + +/***/ +int APP_CC +get_DR_CONTROL_REQ(DR_CONTROL_REQ * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + in_uint32_le(s, self->OutputBufferLength); + in_uint32_le(s, self->InputBufferLength); + in_uint32_le(s, self->IoControlCode); + in_uint8a(s, self->Padding, 20); + if (self->InputBufferLength > 0) { + self->InputBuffer = (BYTE *)g_malloc(sizeof(BYTE) * self->InputBufferLength, 1); + in_uint8a(s, self->InputBuffer, self->InputBufferLength); + } + + return rv; +} + + + +/***/ +int APP_CC +get_DR_CREATE_RSP(DR_CREATE_RSP * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + in_uint32_le(s, self->FileId); + in_uint8(s, self->Information); + + return rv; +} + + + +/***/ +int APP_CC +get_DR_CLOSE_RSP(DR_CLOSE_RSP * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + in_uint8a(s, self->Padding, 5); + + return rv; +} + + + +/***/ +int APP_CC +get_DR_READ_RSP(DR_READ_RSP * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + in_uint32_le(s, self->Length); + if (self->Length > 0) { + if (self->ReadData == NULL) { + self->ReadData = (BYTE *)g_malloc(sizeof(BYTE) * self->Length, 1); + } + in_uint8a(s, self->ReadData, self->Length); + } + + return rv; +} + + + +/***/ +int APP_CC +get_DR_WRITE_RSP(DR_WRITE_RSP * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + in_uint32_le(s, self->Length); + in_uint8(s, self->Padding); + + return rv; +} + + + +/***/ +int APP_CC +get_DR_CONTROL_RSP(DR_CONTROL_RSP * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + in_uint32_le(s, self->OutputBufferLength); + if (self->OutputBufferLength > 0) { + self->OutputBuffer = (BYTE *)g_malloc(sizeof(BYTE) * self->OutputBufferLength, 1); + in_uint8a(s, self->OutputBuffer, self->OutputBufferLength); + } + + return rv; +} + + + +/***/ +int APP_CC +get_RDP_LOCK_INFO(RDP_LOCK_INFO * self, struct stream * s) { + int rv = 0; + + in_uint64_le(s, self->Length); + in_uint64_le(s, self->Offset); + + return rv; +} + + + +/***/ +int APP_CC +get_DR_CORE_DEVICE_ANNOUNCE_RSP(DR_CORE_DEVICE_ANNOUNCE_RSP * self, struct stream * s) { + int rv = 0; + + get_RDPDR_HEADER(&(self->Header), s); + in_uint32_le(s, self->DeviceId); + in_uint32_le(s, self->ResultCode); + + return rv; +} + + + +/***/ +int APP_CC +get_DR_CORE_SERVER_ANNOUNCE_REQ(DR_CORE_SERVER_ANNOUNCE_REQ * self, struct stream * s) { + int rv = 0; + + get_RDPDR_HEADER(&(self->Header), s); + in_uint16_le(s, self->VersionMajor); + in_uint16_le(s, self->VersionMinor); + in_uint32_le(s, self->ClientId); + + return rv; +} + + + +/***/ +int APP_CC +get_DR_CORE_SERVER_CLIENTID_CONFIRM(DR_CORE_SERVER_CLIENTID_CONFIRM * self, struct stream * s) { + int rv = 0; + + get_RDPDR_HEADER(&(self->Header), s); + in_uint16_le(s, self->VersionMajor); + in_uint16_le(s, self->VersionMinor); + in_uint32_le(s, self->ClientId); + + return rv; +} + + + +/***/ +int APP_CC +get_DR_CORE_CAPABILITY_REQ(DR_CORE_CAPABILITY_REQ * self, struct stream * s) { + int rv = 0; + int idx = 0; + + get_RDPDR_HEADER(&(self->Header), s); + in_uint16_le(s, self->numCapabilities); + in_uint16_le(s, self->Padding); + if (self->numCapabilities > 0) { + self->CapabilityMessage = (CAPABILITY_SET *)g_malloc(sizeof(CAPABILITY_SET) * self->numCapabilities, 1); + for (idx = 0; idx < self->numCapabilities; idx++) { + get_CAPABILITY_HEADER(&(self->CapabilityMessage[idx].Header), s); + if (self->CapabilityMessage[idx].Header.CapabilityLength > 0) { + self->CapabilityMessage[idx].capabilityData = (BYTE *)g_malloc(sizeof(BYTE) * self->CapabilityMessage[idx].Header.CapabilityLength, 1); + in_uint8a(s, self->CapabilityMessage[idx].capabilityData, self->CapabilityMessage[idx].Header.CapabilityLength); + } + } + } + + return rv; +} + + + +/***/ +int APP_CC +get_GENERAL_CAPS_SET(GENERAL_CAPS_SET * self, struct stream * s) { + int rv = 0; + + get_CAPABILITY_HEADER(&(self->Header), s); + in_uint32_le(s, self->osType); + in_uint32_le(s, self->osVersion); + in_uint16_le(s, self->protocolMajorVersion); + in_uint16_le(s, self->protocolMinorVersion); + in_uint32_le(s, self->ioCode1); + in_uint32_le(s, self->ioCode2); + in_uint32_le(s, self->extendedPDU); + in_uint32_le(s, self->extraFlags1); + in_uint32_le(s, self->extraFlags2); + in_uint32_le(s, self->SpecialTypeDeviceCap); + + return rv; +} + + + +/***/ +int APP_CC +get_PRINTER_CAPS_SET(PRINTER_CAPS_SET * self, struct stream * s) { + int rv = 0; + + get_CAPABILITY_HEADER(&(self->Header), s); + + return rv; +} + + + +/***/ +int APP_CC +get_PORT_CAPS_SET(PORT_CAPS_SET * self, struct stream * s) { + int rv = 0; + + get_CAPABILITY_HEADER(&(self->Header), s); + + return rv; +} + + + +/***/ +int APP_CC +get_DRIVE_CAPS_SET(DRIVE_CAPS_SET * self, struct stream * s) { + int rv = 0; + + get_CAPABILITY_HEADER(&(self->Header), s); + + return rv; +} + + + +/***/ +int APP_CC +get_SMARTCARD_CAPS_SET(SMARTCARD_CAPS_SET * self, struct stream * s) { + int rv = 0; + + get_CAPABILITY_HEADER(&(self->Header), s); + + return rv; +} + + + +/***/ +int APP_CC +get_DR_CORE_DEVICELIST_ANNOUNCE_REQ(DR_CORE_DEVICELIST_ANNOUNCE_REQ * self, struct stream * s) { + int rv = 0; + int idx = 0; + + get_RDPDR_HEADER(&(self->Header), s); + in_uint32_le(s, self->DeviceCount); + if (self->DeviceCount > 0) { + self->DeviceList = (DEVICE_ANNOUNCE *)g_malloc(sizeof(DEVICE_ANNOUNCE) * self->DeviceCount, 1); + for (idx = 0; idx < self->DeviceCount; idx++) { + get_DEVICE_ANNOUNCE(&(self->DeviceList[idx]), s); + } + } + + return rv; +} + + + +/***/ +int APP_CC +get_DR_DEVICELIST_ANNOUNCE(DR_DEVICELIST_ANNOUNCE * self, struct stream * s) { + int rv = 0; + int idx = 0; + + get_RDPDR_HEADER(&(self->Header), s); + in_uint32_le(s, self->DeviceCount); + if (self->DeviceCount > 0) { + self->DeviceList = (DEVICE_ANNOUNCE **)g_malloc(sizeof(size_t) * self->DeviceCount, 1); + for (idx = 0; idx < self->DeviceCount; idx++) { + self->DeviceList[idx] = (DEVICE_ANNOUNCE *)g_malloc(sizeof(DEVICE_ANNOUNCE), 1); + get_DEVICE_ANNOUNCE(self->DeviceList[idx], s); + } + } + + return rv; +} + + + +/***/ +int APP_CC +get_DR_DEVICELIST_REMOVE(DR_DEVICELIST_REMOVE * self, struct stream * s) { + int rv = 0; + int idx = 0; + + get_RDPDR_HEADER(&(self->Header), s); + in_uint32_le(s, self->DeviceCount); + if (self->DeviceCount > 0) { + self->DeviceIds = (DWORD *)g_malloc(sizeof(DWORD) * self->DeviceCount, 1); + for (idx = 0; idx < self->DeviceCount; idx++) { + in_uint32_le(s, self->DeviceIds[idx]); + } + } + + return rv; +} + + + +/***/ +int APP_CC +get_DR_DRIVE_CORE_DEVICE_IOREQUEST(DR_DRIVE_CORE_DEVICE_IOREQUEST * self, struct stream * s) { + int rv = 0; + + //get_(&(self->Header), s); + + return rv; +} + + + +/***/ +int APP_CC +get_DR_DRIVE_CLOSE_REQ(DR_DRIVE_CLOSE_REQ * self, struct stream * s) { + int rv = 0; + + get_DR_CLOSE_REQ(&(self->DeviceCloseRequest), s); + + return rv; +} + + + +/***/ +int APP_CC +get_DR_DRIVE_READ_REQ(DR_DRIVE_READ_REQ * self, struct stream * s) { + int rv = 0; + + get_DR_READ_REQ(&(self->DeviceReadRequest), s); + + return rv; +} + + + +/***/ +int APP_CC +get_DR_DRIVE_WRITE_REQ(DR_DRIVE_WRITE_REQ * self, struct stream * s) { + int rv = 0; + + get_DR_WRITE_REQ(&(self->DeviceWriteRequest), s); + + return rv; +} + + + +/***/ +int APP_CC +get_DR_DRIVE_CONTROL_REQ(DR_DRIVE_CONTROL_REQ * self, struct stream * s) { + int rv = 0; + + get_DR_CONTROL_REQ(&(self->Header), s); + return rv; +} + + + +/***/ +int APP_CC +get_DR_DRIVE_SET_VOLUME_INFORMATION_REQ(DR_DRIVE_SET_VOLUME_INFORMATION_REQ * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + in_uint32_le(s, self->FsInformationClass); + in_uint32_le(s, self->Length); + in_uint8a(s, self->Padding, 24); + if (self->Length > 0) { + self->SetVolumeBuffer = (BYTE *)g_malloc(sizeof(BYTE) * self->Length, 1); + in_uint8a(s, self->SetVolumeBuffer, self->Length); + } + + return rv; +} + + +/***/ +int APP_CC +get_DR_DRIVE_QUERY_INFORMATION_REQ(DR_DRIVE_QUERY_INFORMATION_REQ * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + in_uint32_le(s, self->FsInformationClass); + in_uint32_le(s, self->Length); + in_uint8a(s, self->Padding, 24); + if (self->Length > 0) { + in_uint8a(s, self->QueryBuffer.bytes, ((((int)(self->Length)) > (int)(sizeof(FILE_BASIC_INFORMATION))) ? (int)sizeof(FILE_BASIC_INFORMATION) : ((int)(self->Length)))); + } + + return rv; +} + + + +/***/ +int APP_CC +get_DR_DRIVE_SET_INFORMATION_REQ(DR_DRIVE_SET_INFORMATION_REQ * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + in_uint32_le(s, self->FsInformationClass); + in_uint32_le(s, self->Length); + in_uint8a(s, self->Padding, 24); + if (self->Length > 0) { + //self->SetBuffer = (BYTE *)g_malloc(sizeof(BYTE) * self->Length, 1); + in_uint8a(s, self->SetBuffer.bytes, self->Length); + } + + return rv; +} + + +/***/ +int APP_CC +get_RDP_FILE_RENAME_INFORMATION(RDP_FILE_RENAME_INFORMATION * self, struct stream * s) { + int rv = 0; + + in_uint8(s, self->ReplaceIfExists); + in_uint8(s, self->RootDirectory); + in_uint32_le(s, self->FileNameLength); + if (self->FileNameLength > 0) { + in_uint8a(s, self->FileName, self->FileNameLength); + } + + return rv; +} + + + +/***/ +int APP_CC +get_DR_DRIVE_LOCK_REQ(DR_DRIVE_LOCK_REQ * self, struct stream * s) { + int rv = 0; + int idx = 0; + + get_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + in_uint32_le(s, self->Operation); + in_uint32_le(s, self->F); + in_uint32_le(s, self->NumLocks); + in_uint8a(s, self->Padding2, 20); + if (self->NumLocks > 0) { + self->Locks = (RDP_LOCK_INFO *)g_malloc(sizeof(RDP_LOCK_INFO) * self->NumLocks, 1); + for (idx = 0; idx < self->NumLocks; idx++) { + get_RDP_LOCK_INFO(&(self->Locks[idx]), s); + } + } + + return rv; +} + + + +/***/ +int APP_CC +get_DR_DRIVE_CORE_DEVICE_IOCOMPLETION(DR_DRIVE_CORE_DEVICE_IOCOMPLETION * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoResponse), s); + + return rv; +} + + + +/***/ +int APP_CC +get_DR_DRIVE_CREATE_RSP(DR_DRIVE_CREATE_RSP * self, struct stream * s) { + int rv = 0; + + get_DR_CREATE_RSP(&(self->DeviceCreateResponse), s); + + return rv; +} + + + +/***/ +int APP_CC +get_DR_DRIVE_CLOSE_RSP(DR_DRIVE_CLOSE_RSP * self, struct stream * s) { + int rv = 0; + + get_DR_CLOSE_RSP(&(self->DeviceCloseResponse), s); + + return rv; +} + + +/***/ +int APP_CC +get_DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP(DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + in_uint32_le(s, self->Length); + if (self->Length > 0) { + //self->Buffer = (BYTE *)g_malloc(sizeof(BYTE) * self->Length, 1); + in_uint8a(s, self->Buffer.bytes, self->Length); + } + //in_uint8(s, self->Padding); + + return rv; +} + + + +/***/ +int APP_CC +get_DR_DRIVE_SET_VOLUME_INFORMATION_RSP(DR_DRIVE_SET_VOLUME_INFORMATION_RSP * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + in_uint32_le(s, self->Length); + + return rv; +} + + + +/***/ +int APP_CC +get_DR_DRIVE_QUERY_INFORMATION_RSP(DR_DRIVE_QUERY_INFORMATION_RSP * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + in_uint32_le(s, self->Length); + if (self->Length > 0 && self->Length < MAX_STREAM) { + in_uint8a(s, self->Buffer.bytes, ((self->Length > sizeof(union _DrDriveQueryInformationRsp_Buffer)) ? sizeof(union _DrDriveQueryInformationRsp_Buffer) : self->Length)); + } + + return rv; +} + + + +/***/ +int APP_CC +get_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + in_uint32_le(s, self->Length); + if (self->Length > 0) { + self->Buffer = (BYTE *)g_malloc(sizeof(BYTE) * self->Length, 1); + in_uint8a(s, self->Buffer, self->Length); + } + //in_uint8(s, self->Padding); + + return rv; +} + + + +/***/ +int APP_CC +get_DR_DRIVE_LOCK_RSP(DR_DRIVE_LOCK_RSP * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + in_uint8a(s, self->Padding, 5); + + return rv; +} + + +/***/ +int APP_CC +send_CAPABILITY_SET(CAPABILITY_SET * self, struct stream * s) { + int rv = 0; + + send_CAPABILITY_HEADER(&(self->Header), s); + if (self->Header.CapabilityLength > 0) { + out_uint8a(s, self->capabilityData, self->Header.CapabilityLength); + } + + return rv; +} + + +/***/ +int APP_CC +send_DEVICE_ANNOUNCE(DEVICE_ANNOUNCE * self, struct stream * s) { + int rv = 0; + + out_uint32_le(s, self->DeviceType); + out_uint32_le(s, self->DeviceId); + out_uint8a(s, self->PreferredDosName, 8); + out_uint32_le(s, self->DeviceDataLength); + if (self->DeviceDataLength > 0) { + out_uint8a(s, self->DeviceData, self->DeviceDataLength); + } + + return rv; +} + + + +/***/ +int APP_CC +send_DR_CLOSE_REQ(DR_CLOSE_REQ * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + out_uint8a(s, self->Padding, 32); + + return rv; +} + + + +/***/ +int APP_CC +send_DR_READ_REQ(DR_READ_REQ * self, struct stream * s) { + int rv = 0; + unsigned char padding[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + send_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + out_uint32_le(s, self->Length); + out_uint64_le(s, self->Offset); + //out_uint8a(s, self->Padding, 20); + out_uint8a(s, padding, 20); + + return rv; +} + + + +/***/ +int APP_CC +send_DR_WRITE_REQ(DR_WRITE_REQ * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + out_uint32_le(s, self->Length); + out_uint64_le(s, self->Offset); + out_uint8a(s, self->Padding, 20); + if (self->Length > 0) { + out_uint8a(s, self->WriteData, self->Length); + } + + return rv; +} + + + +/***/ +int APP_CC +send_DR_CONTROL_REQ(DR_CONTROL_REQ * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + out_uint32_le(s, self->OutputBufferLength); + out_uint32_le(s, self->InputBufferLength); + out_uint32_le(s, self->IoControlCode); + out_uint8a(s, self->Padding, 20); + if (self->InputBufferLength > 0) { + out_uint8a(s, self->InputBuffer, self->InputBufferLength); + } + + return rv; +} + + + +/***/ +int APP_CC +send_DR_CREATE_RSP(DR_CREATE_RSP * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + out_uint32_le(s, self->FileId); + out_uint8(s, self->Information); + + return rv; +} + + + +/***/ +int APP_CC +send_DR_CLOSE_RSP(DR_CLOSE_RSP * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + out_uint8a(s, self->Padding, 5); + + return rv; +} + + + +/***/ +int APP_CC +send_DR_READ_RSP(DR_READ_RSP * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + out_uint32_le(s, self->Length); + if (self->Length > 0 && self->ReadData != NULL) { + out_uint8a(s, self->ReadData, self->Length); + } + + return rv; +} + + + +/***/ +int APP_CC +send_DR_WRITE_RSP(DR_WRITE_RSP * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + out_uint32_le(s, self->Length); + out_uint8(s, self->Padding); + + return rv; +} + + + +/***/ +int APP_CC +send_DR_CONTROL_RSP(DR_CONTROL_RSP * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + out_uint32_le(s, self->OutputBufferLength); + if (self->OutputBufferLength > 0) { + out_uint8a(s, self->OutputBuffer, self->OutputBufferLength); + } + + return rv; +} + + + +/***/ +int APP_CC +send_RDP_LOCK_INFO(RDP_LOCK_INFO * self, struct stream * s) { + int rv = 0; + + out_uint64_le(s, self->Length); + out_uint64_le(s, self->Offset); + + return rv; +} + + + +/***/ +int APP_CC +send_DR_CORE_DEVICE_ANNOUNCE_RSP(DR_CORE_DEVICE_ANNOUNCE_RSP * self, struct stream * s) { + int rv = 0; + + send_RDPDR_HEADER(&(self->Header), s); + out_uint32_le(s, self->DeviceId); + out_uint32_le(s, self->ResultCode); + + return rv; +} + + +/***/ +int APP_CC +send_DR_CORE_SERVER_CLIENTID_CONFIRM(DR_CORE_SERVER_CLIENTID_CONFIRM * self, struct stream * s) { + int rv = 0; + + send_RDPDR_HEADER(&(self->Header), s); + out_uint16_le(s, self->VersionMajor); + out_uint16_le(s, self->VersionMinor); + out_uint32_le(s, self->ClientId); + + return rv; +} + + + +/***/ +int APP_CC +send_DR_CORE_CAPABILITY_REQ(DR_CORE_CAPABILITY_REQ * self, struct stream * s) { + int rv = 0; + int idx = 0; + + send_RDPDR_HEADER(&(self->Header), s); + out_uint16_le(s, self->numCapabilities); + out_uint16_le(s, self->Padding); + if (self->numCapabilities > 0) { + for (idx = 0; idx < self->numCapabilities; idx++) { + send_CAPABILITY_HEADER(&(self->CapabilityMessage[idx].Header), s); + if (self->CapabilityMessage[idx].Header.CapabilityLength > 0) { + out_uint8a(s, self->CapabilityMessage[idx].capabilityData, self->CapabilityMessage[idx].Header.CapabilityLength); + } + } + } + + return rv; +} + + + +/***/ +int APP_CC +send_GENERAL_CAPS_SET(GENERAL_CAPS_SET * self, struct stream * s) { + int rv = 0; + + send_CAPABILITY_HEADER(&(self->Header), s); + out_uint32_le(s, self->osType); + out_uint32_le(s, self->osVersion); + out_uint16_le(s, self->protocolMajorVersion); + out_uint16_le(s, self->protocolMinorVersion); + out_uint32_le(s, self->ioCode1); + out_uint32_le(s, self->ioCode2); + out_uint32_le(s, self->extendedPDU); + out_uint32_le(s, self->extraFlags1); + out_uint32_le(s, self->extraFlags2); + out_uint32_le(s, self->SpecialTypeDeviceCap); + + return rv; +} + + + +/***/ +int APP_CC +send_PRINTER_CAPS_SET(PRINTER_CAPS_SET * self, struct stream * s) { + int rv = 0; + + send_CAPABILITY_HEADER(&(self->Header), s); + + return rv; +} + + + +/***/ +int APP_CC +send_PORT_CAPS_SET(PORT_CAPS_SET * self, struct stream * s) { + int rv = 0; + + send_CAPABILITY_HEADER(&(self->Header), s); + + return rv; +} + + + +/***/ +int APP_CC +send_DRIVE_CAPS_SET(DRIVE_CAPS_SET * self, struct stream * s) { + int rv = 0; + + send_CAPABILITY_HEADER(&(self->Header), s); + + return rv; +} + + + +/***/ +int APP_CC +send_SMARTCARD_CAPS_SET(SMARTCARD_CAPS_SET * self, struct stream * s) { + int rv = 0; + + send_CAPABILITY_HEADER(&(self->Header), s); + + return rv; +} + + + +/***/ +int APP_CC +send_DR_CORE_DEVICELIST_ANNOUNCE_REQ(DR_CORE_DEVICELIST_ANNOUNCE_REQ * self, struct stream * s) { + int rv = 0; + int idx = 0; + + send_RDPDR_HEADER(&(self->Header), s); + out_uint32_le(s, self->DeviceCount); + if (self->DeviceCount > 0) { + for (idx = 0; idx < self->DeviceCount; idx++) { + send_DEVICE_ANNOUNCE(&(self->DeviceList[idx]), s); + } + } + + return rv; +} + + + +/***/ +int APP_CC +send_DR_DEVICELIST_ANNOUNCE(DR_DEVICELIST_ANNOUNCE * self, struct stream * s) { + int rv = 0; + int idx = 0; + + send_RDPDR_HEADER(&(self->Header), s); + out_uint32_le(s, self->DeviceCount); + if (self->DeviceCount > 0) { + for (idx = 0; idx < self->DeviceCount; idx++) { + send_DEVICE_ANNOUNCE(self->DeviceList[idx], s); + } + } + + return rv; +} + + + +/***/ +int APP_CC +send_DR_DEVICELIST_REMOVE(DR_DEVICELIST_REMOVE * self, struct stream * s) { + int rv = 0; + int idx = 0; + + send_RDPDR_HEADER(&(self->Header), s); + out_uint32_le(s, self->DeviceCount); + if (self->DeviceCount > 0) { + for (idx = 0; idx < self->DeviceCount; idx++) { + out_uint32_le(s, self->DeviceIds[idx]); + } + } + + return rv; +} + + + +/***/ +int APP_CC +send_DR_DRIVE_CORE_DEVICE_IOREQUEST(DR_DRIVE_CORE_DEVICE_IOREQUEST * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOREQUEST(&(self->Header), s); + + return rv; +} + + + +/***/ +int APP_CC +send_DR_DRIVE_CLOSE_REQ(DR_DRIVE_CLOSE_REQ * self, struct stream * s) { + int rv = 0; + + send_DR_CLOSE_REQ(&(self->DeviceCloseRequest), s); + + return rv; +} + + + +/***/ +int APP_CC +send_DR_DRIVE_READ_REQ(DR_DRIVE_READ_REQ * self, struct stream * s) { + int rv = 0; + + send_DR_READ_REQ(&(self->DeviceReadRequest), s); + + return rv; +} + + + +/***/ +int APP_CC +send_DR_DRIVE_WRITE_REQ(DR_DRIVE_WRITE_REQ * self, struct stream * s) { + int rv = 0; + + send_DR_WRITE_REQ(&(self->DeviceWriteRequest), s); + + return rv; +} + + + +/***/ +int APP_CC +send_DR_DRIVE_CONTROL_REQ(DR_DRIVE_CONTROL_REQ * self, struct stream * s) { + int rv = 0; + + send_DR_CONTROL_REQ(&(self->Header), s); + return rv; +} + + + +/***/ +int APP_CC +send_DR_DRIVE_SET_VOLUME_INFORMATION_REQ(DR_DRIVE_SET_VOLUME_INFORMATION_REQ * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + out_uint32_le(s, self->FsInformationClass); + out_uint32_le(s, self->Length); + out_uint8a(s, self->Padding, 24); + if (self->Length > 0) { + out_uint8a(s, self->SetVolumeBuffer, self->Length); + } + + return rv; +} + + +/***/ +int APP_CC +send_DR_DRIVE_QUERY_INFORMATION_REQ(DR_DRIVE_QUERY_INFORMATION_REQ * self, struct stream * s) { + int rv = 0; + + if (self == NULL || s == NULL) { + // MDBGLOG("redir","ERROR [send_DR_DRIVE_QUERY_INFORMATION_REQ()]: null pointer"); + rv = -ENOMEM; + } + else { + send_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + out_uint32_le(s, self->FsInformationClass); + out_uint32_le(s, self->Length); + out_uint8a(s, self->Padding, 24); + if (self->Length > 0) { + out_uint8a(s, self->QueryBuffer.bytes, self->Length); + } + } + + return rv; +} + + + +/***/ +int APP_CC +send_DR_DRIVE_SET_INFORMATION_REQ(DR_DRIVE_SET_INFORMATION_REQ * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + out_uint32_le(s, self->FsInformationClass); + out_uint32_le(s, self->Length); + out_uint8a(s, self->Padding, 24); + if (self->Length > 0) { + out_uint8a(s, self->SetBuffer.bytes, self->Length); + } + + return rv; +} + + +/***/ +int APP_CC send_DR_DRIVE_SET_INFORMATION_REQ_rename(DR_DRIVE_SET_INFORMATION_REQ * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + out_uint32_le(s, self->FsInformationClass); + out_uint32_le(s, self->Length); + out_uint8a(s, self->Padding, 24); + send_RDP_FILE_RENAME_INFORMATION(&(self->SetBuffer.RenameInformation), s); + //if (self->Length > 0) { + // out_uint8a(s, self->SetBuffer.bytes, self->Length); + //} + + return rv; +} + + +/***/ +int APP_CC +send_RDP_FILE_RENAME_INFORMATION(RDP_FILE_RENAME_INFORMATION * self, struct stream * s) { + int rv = 0; + + out_uint8(s, self->ReplaceIfExists); + out_uint8(s, self->RootDirectory); + out_uint32_le(s, self->FileNameLength); + if (self->FileNameLength > 0) { + out_uint8a(s, self->FileName, self->FileNameLength); + } + + return rv; +} + + + +/***/ +int APP_CC +send_DR_DRIVE_LOCK_REQ(DR_DRIVE_LOCK_REQ * self, struct stream * s) { + int rv = 0; + int idx = 0; + + send_DR_DEVICE_IOREQUEST(&(self->DeviceIoRequest), s); + out_uint32_le(s, self->Operation); + out_uint32_le(s, self->F); + out_uint32_le(s, self->NumLocks); + out_uint8a(s, self->Padding2, 20); + if (self->NumLocks > 0) { + for (idx = 0; idx < self->NumLocks; idx++) { + send_RDP_LOCK_INFO(&(self->Locks[idx]), s); + } + } + + return rv; +} + + + +/***/ +int APP_CC +send_DR_DRIVE_CORE_DEVICE_IOCOMPLETION(DR_DRIVE_CORE_DEVICE_IOCOMPLETION * self, struct stream * s) { + int rv = 0; + + if (self == NULL || s == NULL) { + rv = -1; + } + else { + send_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoResponse), s); + } + + return rv; +} + + + +/***/ +int APP_CC +send_DR_DRIVE_CREATE_RSP(DR_DRIVE_CREATE_RSP * self, struct stream * s) { + int rv = 0; + + if (self == NULL || s == NULL) { + rv = -1; + } + else { + send_DR_CREATE_RSP(&(self->DeviceCreateResponse), s); + } + + return rv; +} + + + +/***/ +int APP_CC +send_DR_DRIVE_CLOSE_RSP(DR_DRIVE_CLOSE_RSP * self, struct stream * s) { + int rv = 0; + + if (self == NULL || s == NULL) { + rv = -1; + } + else { + send_DR_CLOSE_RSP(&(self->DeviceCloseResponse), s); + } + + return rv; +} + + +/***/ +int APP_CC +send_DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP(DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + out_uint32_le(s, self->Length); + if (self->Length > 0) { + out_uint8a(s, self->Buffer.bytes, self->Length); + } + //out_uint8(s, self->Padding); + + return rv; +} + + + +/***/ +int APP_CC +send_DR_DRIVE_SET_VOLUME_INFORMATION_RSP(DR_DRIVE_SET_VOLUME_INFORMATION_RSP * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + out_uint32_le(s, self->Length); + + return rv; +} + + + +/***/ +int APP_CC +send_DR_DRIVE_QUERY_INFORMATION_RSP(DR_DRIVE_QUERY_INFORMATION_RSP * self, struct stream * s) { + int rv = 0; + int len = 0; + + if (self->Buffer.all.NameInformation.FileNameLength > 0) { + len = (self->Length - self->Buffer.all.NameInformation.FileNameLength); + } + + send_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + out_uint32_le(s, self->Length); + if (self->Length > 0) { + //out_uint8a(s, self->Buffer.bytes, ((self->Length > sizeof(union _DrDriveQueryInformationRsp_Buffer)) ? sizeof(union _DrDriveQueryInformationRsp_Buffer) : self->Length)); + out_uint8a(s, self->Buffer.bytes, (len > sizeof(union _DrDriveQueryInformationRsp_Buffer)) ? sizeof(union _DrDriveQueryInformationRsp_Buffer) : len); + } + if (self->Buffer.all.NameInformation.FileNameLength > 0) { + out_uint8a(s, self->Buffer.all.NameInformation.FileName, self->Buffer.all.NameInformation.FileNameLength); + } + else { + out_uint8(s, 0x00); + } + + return rv; +} + + + +/***/ +int APP_CC +send_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + out_uint32_le(s, self->Length); + if (self->Length > 0) { + out_uint8a(s, self->Buffer, self->Length); + } + //out_uint8(s, self->Padding); + + return rv; +} + + + +/***/ +int APP_CC +send_DR_DRIVE_LOCK_RSP(DR_DRIVE_LOCK_RSP * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + out_uint8a(s, self->Padding, 5); + + return rv; +} + + +/***/ +int APP_CC +send_DR_CORE_SERVER_ANNOUNCE_RSP(DR_CORE_SERVER_ANNOUNCE_RSP * self, struct stream * s) { + int rv = 0; + + send_RDPDR_HEADER(&(self->Header), s); + out_uint16_le(s, self->VersionMajor); + out_uint16_le(s, self->VersionMinor); + out_uint32_le(s, self->ClientId); + + return rv; +} + + + +/***/ +int APP_CC +send_DR_CORE_CLIENT_NAME_REQ(DR_CORE_CLIENT_NAME_REQ * self, struct stream * s) { + int rv = 0; + + send_RDPDR_HEADER(&(self->Header), s); + out_uint32_le(s, self->UnicodeFlag); + out_uint32_le(s, self->CodePage); + out_uint32_le(s, self->ComputerNameLen); + if (self->ComputerNameLen > 0) { + out_uint8a(s, self->ComputerName, self->ComputerNameLen); + } + + return rv; +} + +int APP_CC get_DR_DRIVE_SET_INFORMATION_RSP(DR_DRIVE_SET_INFORMATION_RSP * self, struct stream * s) { + int rv = 0; + + get_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + in_uint32_le(s, self->Length); + //in_uint8(s, self->Padding); + + return rv; +} + +int APP_CC send_DR_DRIVE_SET_INFORMATION_RSP(DR_DRIVE_SET_INFORMATION_RSP * self, struct stream * s) { + int rv = 0; + + send_DR_DEVICE_IOCOMPLETION(&(self->DeviceIoReply), s); + out_uint32_le(s, self->Length); + out_uint8(s, self->Padding); + + return rv; +} + +int APP_CC get_DYNVC_CAPS_VERSION2(DYNVC_CAPS_VERSION2 * self, struct stream * s) { + int rv = 0; + return rv; +} + +int APP_CC get_DYNVC_CAPS_VERSION1(DYNVC_CAPS_VERSION1 * self, struct stream * s) { + int rv = 0; + return rv; +} + +int APP_CC get_DYNVC_CAPS_RSP(DYNVC_CAPS_RSP * self, struct stream * s) { + int rv = 0; + BYTE hdr = 0x00; + + in_uint8(s, hdr); + in_uint8(s, self->Pad); + in_uint16_le(s, self->Version); + + self->Cmd = (hdr & 0xf0) >> 4; + self->Sp = (hdr & 0x0C) >> 2; + self->cbChId = (hdr & 0x03); + + return rv; +} + +int APP_CC get_DYNVC_CREATE_REQ(DYNVC_CREATE_REQ * self, struct stream * s) { + int rv = 0; + int idx = 0; + BYTE ch = 0; + BYTE cid1 = 0; + WORD cid2 = 0; + DWORD cid4 = 0; + BYTE hdr = 0x00; + + in_uint8(s, hdr); + + self->Cmd = (hdr & 0xf0) >> 4; + self->Pri = (hdr & 0x0C) >> 2; + self->cbChId = (hdr & 0x03); + + self->ChannelId = 0; + if (self->cbChId == DRDYNVC_BYTE) { + in_uint8(s, cid1); + self->ChannelId += cid1; + } + if (self->cbChId == DRDYNVC_WORD) { + in_uint16_le(s, cid2); + self->ChannelId += cid2; + } + if (self->cbChId > DRDYNVC_WORD) { + in_uint32_le(s, cid4); + self->ChannelId += cid4; + } + do { + in_uint8(s, ch); + self->ChannelName[idx] = ch; + idx++; + } while (ch != '\0' && idx < 48); + + return rv; +} + +int APP_CC get_DYNVC_CREATE_RSP(DYNVC_CREATE_RSP * self, struct stream * s) { + int rv = 0; + BYTE hdr = 0x00; + union { + BYTE hdr; + DYNVC_CREATE_RSP rsp; + } tmp; + + if (self == NULL || s == NULL) { + rv = -1; + goto end; + } + + in_uint8(s, hdr); + + tmp.rsp.Cmd = (hdr & 0xf0) >> 4; + tmp.rsp.Sp = (hdr & 0x0f) >> 2; + tmp.rsp.cbChId = (hdr & 0x03); + + self->Cmd = tmp.rsp.Cmd; + self->Sp = tmp.rsp.Sp; + self->cbChId = tmp.rsp.cbChId; + + if (tmp.rsp.Cmd != DRDYNVC_CREATE) { + rv = -1; + goto end; + } + tmp.rsp.ChannelId = 0; + if (tmp.rsp.cbChId == DRDYNVC_BYTE) { + BYTE cid1 = 0; + in_uint8(s, cid1); + tmp.rsp.ChannelId += cid1; + } + else if (tmp.rsp.cbChId == DRDYNVC_WORD) { + WORD cid2 = 0; + in_uint16_le(s, cid2); + tmp.rsp.ChannelId += cid2; + } + else if (tmp.rsp.cbChId > DRDYNVC_WORD) { + DWORD cid4 = 0; + in_uint32_le(s, cid4); + tmp.rsp.ChannelId += cid4; + } + in_sint32_le(s, tmp.rsp.CreationStatus); + + self->ChannelId = tmp.rsp.ChannelId; + self->CreationStatus = tmp.rsp.CreationStatus; + + end:; + return rv; +} + +int APP_CC get_DYNVC_DATA_FIRST(DYNVC_DATA_FIRST * self, struct stream * s) { + int rv = 0; + BYTE hdr = 0x00; + union { + BYTE hdr; + DYNVC_DATA_FIRST rsp; + } tmp; + + if (self == NULL || s == NULL) { + rv = -1; + goto end; + } + + in_uint8(s, hdr); + + self->Cmd = (hdr & 0xf0) >> 4; + self->Len = (hdr & 0x0C) >> 2; + self->cbChId = (hdr & 0x03); + tmp.rsp.Cmd = self->Cmd; + tmp.rsp.Len = self->Len; + tmp.rsp.cbChId = self->cbChId; + + if (tmp.rsp.Cmd != DRDYNVC_DATAFIRST) { + rv = -1; + goto end; + } + tmp.rsp.ChannelId = 0; + if (tmp.rsp.cbChId == DRDYNVC_BYTE) { + BYTE cid1 = 0; + in_uint8(s, cid1); + tmp.rsp.ChannelId += cid1; + } + else if (tmp.rsp.cbChId == DRDYNVC_WORD) { + WORD cid2 = 0; + in_uint16_le(s, cid2); + tmp.rsp.ChannelId += cid2; + } + else if (tmp.rsp.cbChId > DRDYNVC_WORD) { + DWORD cid4 = 0; + in_uint32_le(s, cid4); + tmp.rsp.ChannelId += cid4; + } + tmp.rsp.Length = 0; + if (tmp.rsp.Len == DRDYNVC_BYTE) { + BYTE len1 = 0; + in_uint8(s, len1); + tmp.rsp.Length += len1; + } + else if (tmp.rsp.Len == DRDYNVC_WORD) { + WORD len2 = 0; + in_uint16_le(s, len2); + tmp.rsp.Length += len2; + } + else if (tmp.rsp.Len > DRDYNVC_WORD) { + DWORD len4 = 0; + in_uint32_le(s, len4); + tmp.rsp.Length += len4; + } + + self->Cmd = tmp.rsp.Cmd; + self->Len = tmp.rsp.Len; + self->cbChId = tmp.rsp.cbChId; + self->ChannelId = tmp.rsp.ChannelId; + self->Length = tmp.rsp.Length; + + if (tmp.rsp.Length > 0) { + in_uint8a(s, self->Data, tmp.rsp.Length); + } + + end:; + return rv; +} + +int APP_CC get_DYNVC_DATA(DYNVC_DATA * self, struct stream * s) { + int rv = 0; + BYTE hdr = 0x00; + union { + BYTE hdr; + DYNVC_DATA rsp; + } tmp; + + if (self == NULL || s == NULL) { + rv = -1; + goto end; + } + + in_uint8(s, hdr); + + self->Cmd = (hdr & 0xf0) >> 4; + self->Sp = (hdr & 0x0C) >> 2; + self->cbChId = (hdr & 0x03); + tmp.rsp.Cmd = self->Cmd; + tmp.rsp.Sp = self->Sp; + tmp.rsp.cbChId = self->cbChId; + + if (tmp.rsp.Cmd != DRDYNVC_DATA) { + rv = -1; + goto end; + } + tmp.rsp.ChannelId = 0; + if (tmp.rsp.cbChId == DRDYNVC_BYTE) { + BYTE cid1 = 0; + in_uint8(s, cid1); + tmp.rsp.ChannelId += cid1; + } + else if (tmp.rsp.cbChId == DRDYNVC_WORD) { + WORD cid2 = 0; + in_uint16_le(s, cid2); + tmp.rsp.ChannelId += cid2; + } + else if (tmp.rsp.cbChId > DRDYNVC_WORD) { + DWORD cid4 = 0; + in_uint32_le(s, cid4); + tmp.rsp.ChannelId += cid4; + } + if (s->data != NULL && s->p != NULL && s->end > s->p) { + self->Length = (s->end - s->p); + in_uint8a(s, self->Data, self->Length); + } + + self->Cmd = tmp.rsp.Cmd; + self->Sp = tmp.rsp.Sp; + self->cbChId = tmp.rsp.cbChId; + self->ChannelId = tmp.rsp.ChannelId; + + end:; + return rv; +} + +int APP_CC get_DYNVC_CLOSE(DYNVC_CLOSE * self, struct stream * s) { + int rv = 0; + BYTE hdr = 0x00; + union { + BYTE hdr; + DYNVC_CLOSE rsp; + } tmp; + + if (self == NULL || s == NULL) { + rv = -1; + goto end; + } + + in_uint8(s, hdr); + + self->Cmd = (hdr & 0xf0) >> 4; + self->Sp = (hdr & 0x0C) >> 2; + self->cbChId = (hdr & 0x03); + tmp.rsp.Cmd = self->Cmd; + tmp.rsp.Sp = self->Sp; + tmp.rsp.cbChId = self->cbChId; + + if (tmp.rsp.Cmd != DRDYNVC_CLOSE) { + rv = -1; + goto end; + } + tmp.rsp.ChannelId = 0; + if (tmp.rsp.cbChId == DRDYNVC_BYTE) { + BYTE cid1 = 0; + in_uint8(s, cid1); + tmp.rsp.ChannelId += cid1; + } + else if (tmp.rsp.cbChId == DRDYNVC_WORD) { + WORD cid2 = 0; + in_uint16_le(s, cid2); + tmp.rsp.ChannelId += cid2; + } + else if (tmp.rsp.cbChId > DRDYNVC_WORD) { + DWORD cid4 = 0; + in_uint32_le(s, cid4); + tmp.rsp.ChannelId += cid4; + } + + self->Cmd = tmp.rsp.Cmd; + self->Sp = tmp.rsp.Sp; + self->cbChId = tmp.rsp.cbChId; + self->ChannelId = tmp.rsp.ChannelId; + + end:; + return rv; +} + + +/****/ + +int APP_CC send_DYNVC_CAPS_VERSION2(DYNVC_CAPS_VERSION2 * self, struct stream * s) { + int rv = 0; + BYTE hdr = 0x00; + + if (self == NULL || s == NULL) { + rv = -1; + goto end; + } + + //hdr = (BYTE *)self; + hdr = (self->cbChId) | ((self->Sp << 2) | (self->Cmd << 4)); + + out_uint8(s, hdr); + out_uint8(s, self->Pad); + out_uint16_le(s, self->Version); + out_uint16_le(s, self->PriorityCharge0); + out_uint16_le(s, self->PriorityCharge1); + out_uint16_le(s, self->PriorityCharge2); + out_uint16_le(s, self->PriorityCharge3); + + end:; + return rv; +} + +int APP_CC send_DYNVC_CAPS_VERSION1(DYNVC_CAPS_VERSION1 * self, struct stream * s) { + int rv = 0; + BYTE hdr = 0x00; + + if (self == NULL || s == NULL) { + rv = -1; + goto end; + } + + //hdr = (BYTE *)self; + hdr = (self->cbChId) | ((self->Sp << 2) | (self->Cmd << 4)); + + out_uint8(s, hdr); + out_uint8(s, self->Pad); + out_uint16_le(s, self->Version); + + end:; + return rv; +} + +int APP_CC send_DYNVC_CAPS_RSP(DYNVC_CAPS_RSP * self, struct stream * s) { + int rv = 0; + BYTE hdr = 0x00; + + if (self == NULL || s == NULL) { + rv = -1; + goto end; + } + + //hdr = (BYTE *)self; + hdr = (self->cbChId) | ((self->Sp << 2) | (self->Cmd << 4)); + + out_uint8(s, hdr); + out_uint8(s, self->Pad); + out_uint16_le(s, (WORD)(self->Version)); + + end:; + return rv; +} + +int APP_CC send_DYNVC_CREATE_REQ(DYNVC_CREATE_REQ * self, struct stream * s) { + int rv = 0; + int len = 0; + BYTE hdr = 0x00; + BYTE id1 = 0x00; + WORD id2 = 0x0000; + DWORD id4 = 0x00000000; + uint8_t cbChId = 0x00; + uint8_t Pri = 0x00; + uint8_t Cmd = 0x00; + + if (self == NULL || s == NULL) { + rv = -1; + goto end; + } + + //hdr = (BYTE *)self; + //hdr = (self->cbChId & 0x00000003) | (((self->Pri & 0x0000000f) << 2) | ((self->Cmd & 0x000000f0) << 4)); + cbChId = (self->cbChId & 0x00000003); + Pri = (self->Pri & 0x00000003) << 2; + Cmd = (self->Cmd & 0x000000f) << 4; + hdr = Cmd | Pri | cbChId; + + out_uint8(s, hdr); + + switch (self->cbChId) { + case DRDYNVC_BYTE: /* ChannelId is one byte in length */ + id1 += self->ChannelId; + out_uint8(s, id1); + break; + case DRDYNVC_WORD: /* ChannelId is two bytes in length */ + id2 += self->ChannelId; + out_uint16_le(s, id2); + break; + case DRDYNVC_DWORD: /* ChannelId is four bytes in length */ + case DRDYNVC_DWORD_ALT: + id4 += self->ChannelId; + out_uint32_le(s, id4); + break; + } + + len = g_strnlen((char *)(self->ChannelName), 47); + if (len > 0) { + out_uint8a(s, self->ChannelName, len); + out_uint8(s, '\0'); + } + + end:; + return rv; +} + +int APP_CC send_DYNVC_CREATE_RSP(DYNVC_CREATE_RSP * self, struct stream * s) { + int rv = 0; + BYTE hdr = 0x00; + BYTE id1 = 0x00; + WORD id2 = 0x0000; + DWORD id4 = 0x00000000; + + if (self == NULL || s == NULL) { + rv = -1; + goto end; + } + + //hdr = (BYTE *)self; + hdr = (self->cbChId) | ((self->Sp << 2) | (self->Cmd << 4)); + out_uint8(s, hdr); + + switch (self->cbChId) { + case DRDYNVC_BYTE: /* ChannelId is one byte in length */ + id1 += self->ChannelId; + out_uint8(s, id1); + break; + case DRDYNVC_WORD: /* ChannelId is two bytes in length */ + id2 += self->ChannelId; + out_uint16_le(s, id2); + break; + case DRDYNVC_DWORD: /* ChannelId is four bytes in length */ + case DRDYNVC_DWORD_ALT: + default: + id4 += self->ChannelId; + out_uint32_le(s, id4); + break; + } + + out_uint32_le(s, self->CreationStatus); + + end:; + return rv; +} + +int APP_CC send_DYNVC_DATA_FIRST(DYNVC_DATA_FIRST * self, struct stream * s) { + int rv = 0; + BYTE hdr = 0; + BYTE id1 = 0x00; + WORD id2 = 0x0000; + DWORD id4 = 0x00000000; + uint8_t cbChId = 0x00; + uint8_t Len = 0x00; + uint8_t Cmd = 0x00; + size_t l1 = 0; + size_t l2 = 0; + + if (self == NULL || s == NULL) { + rv = -1; + goto end; + } + + //hdr = (BYTE *)self; + //hdr = (self->cbChId) | ((self->Len << 2) | (self->Cmd << 4)); + cbChId = (self->cbChId & 0x00000003); + Len = (self->Len & 0x00000003) << 2; + Cmd = (self->Cmd & 0x000000f) << 4; + hdr = Cmd | Len | cbChId; + + out_uint8(s, hdr); + + switch (self->cbChId) { + case DRDYNVC_BYTE: /* ChannelId is one byte in length */ + l1 = 1; + id1 = (self->ChannelId & 0x000000ff); + out_uint8(s, id1); + break; + case DRDYNVC_WORD: /* ChannelId is two bytes in length */ + l1 = 2; + id2 = (self->ChannelId & 0x0000ffff); + out_uint16_le(s, id2); + break; + case DRDYNVC_DWORD: /* ChannelId is four bytes in length */ + case DRDYNVC_DWORD_ALT: + l1 = 4; + id4 = self->ChannelId; + out_uint32_le(s, id4); + break; + } + + id1 = 0; + id2 = 0; + id4 = 0; + switch (self->Len) { + case DRDYNVC_BYTE: /* Length is one byte in length */ + l2 = 1; + id1 = (self->Length & 0x000000ff); + out_uint8(s, id1); + break; + case DRDYNVC_WORD: /* Length is two bytes in length */ + l2 = 2; + id2 = (self->Length & 0x0000ffff); + out_uint16_le(s, id2); + break; + case DRDYNVC_DWORD: /* Length is four bytes in length */ + case DRDYNVC_DWORD_ALT: + l2 = 4; + id4 = self->Length; + out_uint32_le(s, id4); + break; + } + + if (self->Length > 0) { + out_uint8a(s, self->Data, MIN((self->Length), (DRDYNVC_MAX_PDU - (1 + l1 + l2)))); + } + + end:; + return rv; +} + +int APP_CC send_DYNVC_DATA(DYNVC_DATA * self, struct stream * s) { + int rv = 0; + BYTE hdr = 0x00; + BYTE id1 = 0x00; + WORD id2 = 0x0000; + DWORD id4 = 0x00000000; + uint8_t cbChId = 0x00; + uint8_t Sp = 0x00; + uint8_t Cmd = 0x00; + size_t l1 = 0; + + if (self == NULL || s == NULL) { + rv = -1; + goto end; + } + + //hdr = (BYTE *)self; + //hdr = (self->cbChId) | ((self->Sp << 2) | (self->Cmd << 4)); + cbChId = (self->cbChId & 0x00000003); + Sp = (self->Sp & 0x00000003) << 2; + Cmd = (self->Cmd & 0x000000f) << 4; + hdr = Cmd | Sp | cbChId; + + out_uint8(s, hdr); + + switch (self->cbChId) { + case DRDYNVC_BYTE: /* ChannelId is one byte in length */ + l1 = 1; + id1 = (self->ChannelId & 0x000000ff); + out_uint8(s, id1); + break; + case DRDYNVC_WORD: /* ChannelId is two bytes in length */ + l1 = 2; + id2 = (self->ChannelId & 0x0000ffff); + out_uint16_le(s, id2); + break; + case DRDYNVC_DWORD: /* ChannelId is four bytes in length */ + case DRDYNVC_DWORD_ALT: + l1 = 4; + id4 = self->ChannelId; + out_uint32_le(s, id4); + break; + } + + if (self->Length > 0) { + out_uint8a(s, self->Data, MIN(self->Length, (DRDYNVC_MAX_PDU - (1 + l1)))); + } + + end:; + return rv; +} + +int APP_CC send_DYNVC_CLOSE(DYNVC_CLOSE * self, struct stream * s) { + int rv = 0; + BYTE hdr = 0; + BYTE id1 = 0x00; + WORD id2 = 0x0000; + DWORD id4 = 0x00000000; + uint8_t cbChId = 0x00; + uint8_t Sp = 0x00; + uint8_t Cmd = 0x00; + + if (self == NULL || s == NULL) { + rv = -1; + goto end; + } + + //hdr = (BYTE *)self; + //hdr = (self->cbChId) | ((self->Sp << 2) | (self->Cmd << 4)); + cbChId = (self->cbChId & 0x00000003); + Sp = (self->Sp & 0x00000003) << 2; + Cmd = (self->Cmd & 0x000000f) << 4; + hdr = Cmd | Sp | cbChId; + + out_uint8(s, hdr); + + switch (self->cbChId) { + case DRDYNVC_BYTE: /* ChannelId is one byte in length */ + id1 = (self->ChannelId & 0x000000ff); + out_uint8(s, id1); + break; + case DRDYNVC_WORD: /* ChannelId is two bytes in length */ + id2 = (self->ChannelId & 0x0000ffff); + out_uint16_le(s, id2); + break; + case DRDYNVC_DWORD: /* ChannelId is four bytes in length */ + case DRDYNVC_DWORD_ALT: + id4 = self->ChannelId; + out_uint32_le(s, id4); + break; + } + + end:; + return rv; +} + + + +/* +int APP_CC +send_( * self, struct stream * s) { + int rv = 0; + + return rv; +} + +int APP_CC +get_( * self, struct stream * s) { + int rv = 0; + + return rv; +} +*/ + +/********************************************************************** + * END: SENDERS / GETTERS + **********************************************************************/ + +/********************************************************************** + * BEGIN: DESTRUCTORS + **********************************************************************/ + +void APP_CC destroy_RDPDR_HEADER(RDPDR_HEADER * self) { +} + +void APP_CC destroy_CAPABILITY_HEADER(CAPABILITY_HEADER * self) { +} + +void APP_CC destroy_CAPABILITY_SET(CAPABILITY_SET * self) { +} + +void APP_CC destroy_DEVICE_ANNOUNCE(DEVICE_ANNOUNCE * self) { +} + +void APP_CC destroy_DR_DEVICE_IOREQUEST(DR_DEVICE_IOREQUEST * self) { +} + +void APP_CC destroy_DR_CREATE_REQ(DR_CREATE_REQ * self) { +} + +void APP_CC destroy_DR_CLOSE_REQ(DR_CLOSE_REQ * self) { +} + +void APP_CC destroy_DR_READ_REQ(DR_READ_REQ * self) { +} + +void APP_CC destroy_DR_WRITE_REQ(DR_WRITE_REQ * self) { +} + +void APP_CC destroy_DR_CONTROL_REQ(DR_CONTROL_REQ * self) { +} + +void APP_CC destroy_DR_DEVICE_IOCOMPLETION(DR_DEVICE_IOCOMPLETION * self) { +} + +void APP_CC destroy_DR_CREATE_RSP(DR_CREATE_RSP * self) { +} + +void APP_CC destroy_DR_CLOSE_RSP(DR_CLOSE_RSP * self) { +} + +void APP_CC destroy_DR_READ_RSP(DR_READ_RSP * self) { +} + +void APP_CC destroy_DR_WRITE_RSP(DR_WRITE_RSP * self) { +} + +void APP_CC destroy_DR_CONTROL_RSP(DR_CONTROL_RSP * self) { +} + +void APP_CC destroy_RDP_LOCK_INFO(RDP_LOCK_INFO * self) { +} + +void APP_CC destroy_DR_CORE_DEVICE_ANNOUNCE_RSP(DR_CORE_DEVICE_ANNOUNCE_RSP * self) { +} + +void APP_CC destroy_DR_CORE_SERVER_ANNOUNCE_REQ(DR_CORE_SERVER_ANNOUNCE_REQ * self) { +} + +void APP_CC destroy_DR_CORE_SERVER_ANNOUNCE_RSP(DR_CORE_SERVER_ANNOUNCE_RSP * self) { +} + +void APP_CC destroy_DR_CORE_CLIENT_NAME_REQ(DR_CORE_CLIENT_NAME_REQ * self) { +} + +void APP_CC destroy_DR_CORE_SERVER_CLIENTID_CONFIRM(DR_CORE_SERVER_CLIENTID_CONFIRM * self) { +} + +void APP_CC destroy_DR_CORE_CAPABILITY_REQ(DR_CORE_CAPABILITY_REQ * self) { +} + +void APP_CC destroy_GENERAL_CAPS_SET(GENERAL_CAPS_SET * self) { +} + +void APP_CC destroy_PRINTER_CAPS_SET(PRINTER_CAPS_SET * self) { +} + +void APP_CC destroy_PORT_CAPS_SET(PORT_CAPS_SET * self) { +} + +void APP_CC destroy_DRIVE_CAPS_SET(DRIVE_CAPS_SET * self) { +} + +void APP_CC destroy_SMARTCARD_CAPS_SET(SMARTCARD_CAPS_SET * self) { +} + +void APP_CC destroy_DR_CORE_DEVICELIST_ANNOUNCE_REQ(DR_CORE_DEVICELIST_ANNOUNCE_REQ * self) { +} + +void APP_CC destroy_DR_DEVICELIST_ANNOUNCE(DR_DEVICELIST_ANNOUNCE * self) { +} + +void APP_CC destroy_DR_DEVICELIST_REMOVE(DR_DEVICELIST_REMOVE * self) { +} + +void APP_CC destroy_DR_DRIVE_CORE_DEVICE_IOREQUEST(DR_DRIVE_CORE_DEVICE_IOREQUEST * self) { +} + +void APP_CC destroy_DR_DRIVE_CREATE_REQ(DR_DRIVE_CREATE_REQ * self) { +} + +void APP_CC destroy_DR_DRIVE_CLOSE_REQ(DR_DRIVE_CLOSE_REQ * self) { +} + +void APP_CC destroy_DR_DRIVE_READ_REQ(DR_DRIVE_READ_REQ * self) { +} + +void APP_CC destroy_DR_DRIVE_WRITE_REQ(DR_DRIVE_WRITE_REQ * self) { +} + +void APP_CC destroy_DR_DRIVE_CONTROL_REQ(DR_DRIVE_CONTROL_REQ * self) { +} + +void APP_CC destroy_DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ(DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ * self) { +} + +void APP_CC destroy_DR_DRIVE_SET_VOLUME_INFORMATION_REQ(DR_DRIVE_SET_VOLUME_INFORMATION_REQ * self) { +} + +void APP_CC destroy_DR_DRIVE_QUERY_INFORMATION_REQ(DR_DRIVE_QUERY_INFORMATION_REQ * self) { +} + +void APP_CC destroy_DR_DRIVE_SET_INFORMATION_REQ(DR_DRIVE_SET_INFORMATION_REQ * self) { +} + +void APP_CC destroy_RDP_FILE_RENAME_INFORMATION(RDP_FILE_RENAME_INFORMATION * self) { +} + +void APP_CC destroy_DR_DRIVE_QUERY_DIRECTORY_REQ(DR_DRIVE_QUERY_DIRECTORY_REQ * self) { +} + +void APP_CC destroy_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ * self) { +} + +void APP_CC destroy_DR_DRIVE_LOCK_REQ(DR_DRIVE_LOCK_REQ * self) { +} + +void APP_CC destroy_DR_DRIVE_CORE_DEVICE_IOCOMPLETION(DR_DRIVE_CORE_DEVICE_IOCOMPLETION * self) { +} + +void APP_CC destroy_DR_DRIVE_CREATE_RSP(DR_DRIVE_CREATE_RSP * self) { +} + +void APP_CC destroy_DR_DRIVE_CLOSE_RSP(DR_DRIVE_CLOSE_RSP * self) { +} + +void APP_CC destroy_DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP(DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP * self) { +} + +void APP_CC destroy_DR_DRIVE_SET_VOLUME_INFORMATION_RSP(DR_DRIVE_SET_VOLUME_INFORMATION_RSP * self) { +} + +void APP_CC destroy_DR_DRIVE_QUERY_INFORMATION_RSP(DR_DRIVE_QUERY_INFORMATION_RSP * self) { +} + +void APP_CC destroy_DR_DRIVE_QUERY_DIRECTORY_RSP(DR_DRIVE_QUERY_DIRECTORY_RSP * self) { +} + +void APP_CC destroy_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP * self) { +} + +void APP_CC destroy_DR_DRIVE_LOCK_RSP(DR_DRIVE_LOCK_RSP * self) { +} + +void APP_CC destroy_DR_CORE_USER_LOGGEDON(DR_CORE_USER_LOGGEDON * self) { +} + +void APP_CC destroy_DYNVC_CAPS_VERSION2(DYNVC_CAPS_VERSION2 * self) { +} + +void APP_CC destroy_DYNVC_CAPS_VERSION1(DYNVC_CAPS_VERSION1 * self) { +} + +void APP_CC destroy_DYNVC_CAPS_RSP(DYNVC_CAPS_RSP * self) { +} + +void APP_CC destroy_DYNVC_CREATE_REQ(DYNVC_CREATE_REQ * self) { +} + +void APP_CC destroy_DYNVC_CREATE_RSP(DYNVC_CREATE_RSP * self) { +} + +void APP_CC destroy_DYNVC_DATA_FIRST(DYNVC_DATA_FIRST * self) { +} + +void APP_CC destroy_DYNVC_DATA(DYNVC_DATA * self) { +} + +void APP_CC destroy_DYNVC_CLOSE(DYNVC_CLOSE * self) { +} + + + +/********************************************************************** + * END: DESTRUCTORS + **********************************************************************/ + +/*****************************************************************************/ +void * APP_CC rdpdr_inst(const char * cname) { + void *res = NULL; + if (!g_strcasecmp(cname,"RDPDR_HEADER")) { + res = (void *)g_malloc(sizeof(RDPDR_HEADER),1); + ((RDPDR_HEADER *)res)->__destructor = &destroy_RDPDR_HEADER; + ((RDPDR_HEADER *)res)->out = &send_RDPDR_HEADER; + ((RDPDR_HEADER *)res)->in = &get_RDPDR_HEADER; + construct_RDPDR_HEADER(res); + } + else if (!g_strcasecmp(cname,"CAPABILITY_HEADER")) { + res = (void *)g_malloc(sizeof(CAPABILITY_HEADER),1); + ((CAPABILITY_HEADER *)res)->__destructor = &destroy_CAPABILITY_HEADER; + ((CAPABILITY_HEADER *)res)->out = &send_CAPABILITY_HEADER; + ((CAPABILITY_HEADER *)res)->in = &get_CAPABILITY_HEADER; + construct_CAPABILITY_HEADER(res); + } + else if (!g_strcasecmp(cname,"CAPABILITY_SET")) { + res = (void *)g_malloc(sizeof(CAPABILITY_SET),1); + ((CAPABILITY_SET *)res)->__destructor = &destroy_CAPABILITY_SET; + construct_CAPABILITY_SET(res); + } + else if (!g_strcasecmp(cname,"DEVICE_ANNOUNCE")) { + res = (void *)g_malloc(sizeof(DEVICE_ANNOUNCE),1); + ((DEVICE_ANNOUNCE *)res)->__destructor = &destroy_DEVICE_ANNOUNCE; + construct_DEVICE_ANNOUNCE(res); + } + else if (!g_strcasecmp(cname,"DR_DEVICE_IOREQUEST")) { + res = (void *)g_malloc(sizeof(DR_DEVICE_IOREQUEST),1); + ((DR_DEVICE_IOREQUEST *)res)->Header.out = &send_RDPDR_HEADER; + ((DR_DEVICE_IOREQUEST *)res)->Header.in = &get_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DEVICE_IOREQUEST *)res)->Header)); + ((DR_DEVICE_IOREQUEST *)res)->__destructor = &destroy_DR_DEVICE_IOREQUEST; + ((DR_DEVICE_IOREQUEST *)res)->out = &send_DR_DEVICE_IOREQUEST; + ((DR_DEVICE_IOREQUEST *)res)->in = &get_DR_DEVICE_IOREQUEST; + construct_DR_DEVICE_IOREQUEST(res); + } + else if (!g_strcasecmp(cname,"DR_CREATE_REQ")) { + res = (void *)g_malloc(sizeof(DR_CREATE_REQ),1); + ((DR_CREATE_REQ *)res)->DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + ((DR_CREATE_REQ *)res)->DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_CREATE_REQ *)res)->DeviceIoRequest.Header)); + ((DR_CREATE_REQ *)res)->DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + ((DR_CREATE_REQ *)res)->DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + construct_DR_DEVICE_IOREQUEST(&(((DR_CREATE_REQ *)res)->DeviceIoRequest)); + ((DR_CREATE_REQ *)res)->__destructor = &destroy_DR_CREATE_REQ; + ((DR_CREATE_REQ *)res)->out = &send_DR_CREATE_REQ; + ((DR_CREATE_REQ *)res)->in = &get_DR_CREATE_REQ; + construct_DR_CREATE_REQ(res); + } + else if (!g_strcasecmp(cname,"DR_CLOSE_REQ")) { + res = (void *)g_malloc(sizeof(DR_CLOSE_REQ),1); + ((DR_CLOSE_REQ *)res)->DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + ((DR_CLOSE_REQ *)res)->DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_CLOSE_REQ *)res)->DeviceIoRequest.Header)); + ((DR_CLOSE_REQ *)res)->DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + ((DR_CLOSE_REQ *)res)->DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + construct_DR_DEVICE_IOREQUEST(&(((DR_CLOSE_REQ *)res)->DeviceIoRequest)); + ((DR_CLOSE_REQ *)res)->__destructor = &destroy_DR_CLOSE_REQ; + ((DR_CLOSE_REQ *)res)->out = &send_DR_CLOSE_REQ; + ((DR_CLOSE_REQ *)res)->in = &get_DR_CLOSE_REQ; + construct_DR_CLOSE_REQ(res); + } + else if (!g_strcasecmp(cname,"DR_READ_REQ")) { + res = (void *)g_malloc(sizeof(DR_READ_REQ),1); + ((DR_READ_REQ *)res)->DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + ((DR_READ_REQ *)res)->DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_READ_REQ *)res)->DeviceIoRequest.Header)); + ((DR_READ_REQ *)res)->DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + ((DR_READ_REQ *)res)->DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + construct_DR_DEVICE_IOREQUEST(&(((DR_READ_REQ *)res)->DeviceIoRequest)); + ((DR_READ_REQ *)res)->__destructor = &destroy_DR_READ_REQ; + ((DR_READ_REQ *)res)->out = &send_DR_READ_REQ; + ((DR_READ_REQ *)res)->in = &get_DR_READ_REQ; + construct_DR_READ_REQ(res); + } + else if (!g_strcasecmp(cname,"DR_WRITE_REQ")) { + res = (void *)g_malloc(sizeof(DR_WRITE_REQ),1); + ((DR_WRITE_REQ *)res)->DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + ((DR_WRITE_REQ *)res)->DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_WRITE_REQ *)res)->DeviceIoRequest.Header)); + ((DR_WRITE_REQ *)res)->DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + ((DR_WRITE_REQ *)res)->DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + construct_DR_DEVICE_IOREQUEST(&(((DR_WRITE_REQ *)res)->DeviceIoRequest)); + ((DR_WRITE_REQ *)res)->__destructor = &destroy_DR_WRITE_REQ; + ((DR_WRITE_REQ *)res)->out = &send_DR_WRITE_REQ; + ((DR_WRITE_REQ *)res)->in = &get_DR_WRITE_REQ; + construct_DR_WRITE_REQ(res); + } + else if (!g_strcasecmp(cname,"DR_CONTROL_REQ")) { + res = (void *)g_malloc(sizeof(DR_CONTROL_REQ),1); + ((DR_CONTROL_REQ *)res)->DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + ((DR_CONTROL_REQ *)res)->DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_CONTROL_REQ *)res)->DeviceIoRequest.Header)); + ((DR_CONTROL_REQ *)res)->DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + ((DR_CONTROL_REQ *)res)->DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + construct_DR_DEVICE_IOREQUEST(&(((DR_CONTROL_REQ *)res)->DeviceIoRequest)); + ((DR_CONTROL_REQ *)res)->__destructor = &destroy_DR_CONTROL_REQ; + ((DR_CONTROL_REQ *)res)->out = &send_DR_CONTROL_REQ; + ((DR_CONTROL_REQ *)res)->in = &get_DR_CONTROL_REQ; + construct_DR_CONTROL_REQ(res); + } + else if (!g_strcasecmp(cname,"DR_DEVICE_IOCOMPLETION")) { + res = (void *)g_malloc(sizeof(DR_DEVICE_IOCOMPLETION),1); + ((DR_DEVICE_IOCOMPLETION *)res)->Header.out = &send_RDPDR_HEADER; + ((DR_DEVICE_IOCOMPLETION *)res)->Header.in = &get_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DEVICE_IOCOMPLETION *)res)->Header)); + ((DR_DEVICE_IOCOMPLETION *)res)->__destructor = &destroy_DR_DEVICE_IOCOMPLETION; + ((DR_DEVICE_IOCOMPLETION *)res)->in = &get_DR_DEVICE_IOCOMPLETION; + ((DR_DEVICE_IOCOMPLETION *)res)->out = &send_DR_DEVICE_IOCOMPLETION; + construct_DR_DEVICE_IOCOMPLETION(res); + } + else if (!g_strcasecmp(cname,"DR_CREATE_RSP")) { + res = (void *)g_malloc(sizeof(DR_CREATE_RSP),1); + construct_RDPDR_HEADER(&(((DR_CREATE_RSP *)res)->DeviceIoReply.Header)); + construct_DR_DEVICE_IOCOMPLETION(&(((DR_CREATE_RSP *)res)->DeviceIoReply)); + construct_DR_CREATE_RSP(res); + ((DR_CREATE_RSP *)res)->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + ((DR_CREATE_RSP *)res)->DeviceIoReply.Header.in = &get_RDPDR_HEADER; + ((DR_CREATE_RSP *)res)->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + ((DR_CREATE_RSP *)res)->DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + ((DR_CREATE_RSP *)res)->DeviceIoReply.Header.__destructor = NULL; + ((DR_CREATE_RSP *)res)->DeviceIoReply.__destructor = NULL; + ((DR_CREATE_RSP *)res)->__destructor = NULL; + ((DR_CREATE_RSP *)res)->out = &send_DR_CREATE_RSP; + ((DR_CREATE_RSP *)res)->in = &get_DR_CREATE_RSP; + } + else if (!g_strcasecmp(cname,"DR_CLOSE_RSP")) { + res = (void *)g_malloc(sizeof(DR_CLOSE_RSP),1); + construct_RDPDR_HEADER(&(((DR_CLOSE_RSP *)res)->DeviceIoReply.Header)); + construct_DR_DEVICE_IOCOMPLETION(&(((DR_CLOSE_RSP *)res)->DeviceIoReply)); + construct_DR_CLOSE_RSP(res); + ((DR_CLOSE_RSP *)res)->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + ((DR_CLOSE_RSP *)res)->DeviceIoReply.Header.in = &get_RDPDR_HEADER; + ((DR_CLOSE_RSP *)res)->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + ((DR_CLOSE_RSP *)res)->DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + ((DR_CLOSE_RSP *)res)->DeviceIoReply.Header.__destructor = NULL; + ((DR_CLOSE_RSP *)res)->DeviceIoReply.__destructor = NULL; + ((DR_CLOSE_RSP *)res)->__destructor = NULL; + ((DR_CLOSE_RSP *)res)->out = &send_DR_CLOSE_RSP; + ((DR_CLOSE_RSP *)res)->in = &get_DR_CLOSE_RSP; + } + else if (!g_strcasecmp(cname,"DR_READ_RSP") || !g_strcasecmp(cname, "DR_DRIVE_READ_RSP")) { + res = (void *)g_malloc(sizeof(DR_READ_RSP),1); + ((DR_READ_RSP *)res)->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + ((DR_READ_RSP *)res)->DeviceIoReply.Header.in = &get_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_READ_RSP *)res)->DeviceIoReply.Header)); + ((DR_READ_RSP *)res)->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + ((DR_READ_RSP *)res)->DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + construct_DR_DEVICE_IOCOMPLETION(&(((DR_READ_RSP *)res)->DeviceIoReply)); + ((DR_READ_RSP *)res)->__destructor = &destroy_DR_READ_RSP; + ((DR_READ_RSP *)res)->out = &send_DR_READ_RSP; + ((DR_READ_RSP *)res)->in = &get_DR_READ_RSP; + construct_DR_READ_RSP(res); + } + else if (!g_strcasecmp(cname,"DR_WRITE_RSP") || !g_strcasecmp(cname,"DR_DRIVE_WRITE_RSP")) { + res = (void *)g_malloc(sizeof(DR_WRITE_RSP),1); + ((DR_WRITE_RSP *)res)->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + ((DR_WRITE_RSP *)res)->DeviceIoReply.Header.in = &get_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_WRITE_RSP *)res)->DeviceIoReply.Header)); + ((DR_WRITE_RSP *)res)->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + ((DR_WRITE_RSP *)res)->DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + construct_DR_DEVICE_IOCOMPLETION(&(((DR_WRITE_RSP *)res)->DeviceIoReply)); + ((DR_WRITE_RSP *)res)->__destructor = &destroy_DR_WRITE_RSP; + ((DR_WRITE_RSP *)res)->out = &send_DR_WRITE_RSP; + ((DR_WRITE_RSP *)res)->in = &get_DR_WRITE_RSP; + construct_DR_WRITE_RSP(res); + } + else if (!g_strcasecmp(cname,"DR_CONTROL_RSP") || !g_strcasecmp(cname,"DR_DRIVE_CONTROL_RSP")) { + res = (void *)g_malloc(sizeof(DR_CONTROL_RSP),1); + ((DR_CONTROL_RSP *)res)->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + ((DR_CONTROL_RSP *)res)->DeviceIoReply.Header.in = &get_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_CONTROL_RSP *)res)->DeviceIoReply.Header)); + ((DR_CONTROL_RSP *)res)->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + ((DR_CONTROL_RSP *)res)->DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + construct_DR_DEVICE_IOCOMPLETION(&(((DR_CONTROL_RSP *)res)->DeviceIoReply)); + ((DR_CONTROL_RSP *)res)->__destructor = &destroy_DR_CONTROL_RSP; + ((DR_CONTROL_RSP *)res)->out = &send_DR_CONTROL_RSP; + ((DR_CONTROL_RSP *)res)->in = &get_DR_CONTROL_RSP; + construct_DR_CONTROL_RSP(res); + } + else if (!g_strcasecmp(cname,"RDP_LOCK_INFO")) { + res = (void *)g_malloc(sizeof(RDP_LOCK_INFO),1); + ((RDP_LOCK_INFO *)res)->__destructor = &destroy_RDP_LOCK_INFO; + ((RDP_LOCK_INFO *)res)->out = &send_RDP_LOCK_INFO; + ((RDP_LOCK_INFO *)res)->in = &get_RDP_LOCK_INFO; + construct_RDP_LOCK_INFO(res); + } + else if (!g_strcasecmp(cname,"DR_CORE_DEVICE_ANNOUNCE_RSP")) { + res = (void *)g_malloc(sizeof(DR_CORE_DEVICE_ANNOUNCE_RSP),1); + ((DR_CORE_DEVICE_ANNOUNCE_RSP *)res)->Header.out = &send_RDPDR_HEADER; + ((DR_CORE_DEVICE_ANNOUNCE_RSP *)res)->Header.in = &get_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_CORE_DEVICE_ANNOUNCE_RSP *)res)->Header)); + ((DR_CORE_DEVICE_ANNOUNCE_RSP *)res)->__destructor = &destroy_DR_CORE_DEVICE_ANNOUNCE_RSP; + ((DR_CORE_DEVICE_ANNOUNCE_RSP *)res)->in = &get_DR_CORE_DEVICE_ANNOUNCE_RSP; + ((DR_CORE_DEVICE_ANNOUNCE_RSP *)res)->out = &send_DR_CORE_DEVICE_ANNOUNCE_RSP; + construct_DR_CORE_DEVICE_ANNOUNCE_RSP(res); + } + else if (!g_strcasecmp(cname,"DR_CORE_SERVER_ANNOUNCE_REQ")) { + res = (void *)g_malloc(sizeof(DR_CORE_SERVER_ANNOUNCE_REQ),1); + ((DR_CORE_SERVER_ANNOUNCE_REQ *)res)->Header.out = &send_RDPDR_HEADER; + ((DR_CORE_SERVER_ANNOUNCE_REQ *)res)->Header.in = &get_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_CORE_SERVER_ANNOUNCE_REQ *)res)->Header)); + ((DR_CORE_SERVER_ANNOUNCE_REQ *)res)->Header.Component = RDPDR_CTYP_CORE; + ((DR_CORE_SERVER_ANNOUNCE_REQ *)res)->Header.PacketId = PAKID_CORE_SERVER_ANNOUNCE; + ((DR_CORE_SERVER_ANNOUNCE_REQ *)res)->VersionMajor = 0x0001; /* [MS-RDPEFS] @ 2.2.2.2 */ + ((DR_CORE_SERVER_ANNOUNCE_REQ *)res)->VersionMinor = 0x000C; /* " */ + ((DR_CORE_SERVER_ANNOUNCE_REQ *)res)->__destructor = &destroy_DR_CORE_SERVER_ANNOUNCE_REQ; + ((DR_CORE_SERVER_ANNOUNCE_REQ *)res)->in = &get_DR_CORE_SERVER_ANNOUNCE_REQ; + ((DR_CORE_SERVER_ANNOUNCE_REQ *)res)->out = &send_DR_CORE_SERVER_ANNOUNCE_REQ; + construct_DR_CORE_SERVER_ANNOUNCE_REQ(res); + } + else if (!g_strcasecmp(cname,"DR_CORE_SERVER_ANNOUNCE_RSP")) { + res = (void *)g_malloc(sizeof(DR_CORE_SERVER_ANNOUNCE_RSP),1); + ((DR_CORE_SERVER_ANNOUNCE_RSP *)res)->Header.out = &send_RDPDR_HEADER; + ((DR_CORE_SERVER_ANNOUNCE_RSP *)res)->Header.in = &get_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_CORE_SERVER_ANNOUNCE_RSP *)res)->Header)); + ((DR_CORE_SERVER_ANNOUNCE_RSP *)res)->__destructor = &destroy_DR_CORE_SERVER_ANNOUNCE_RSP; + ((DR_CORE_SERVER_ANNOUNCE_RSP *)res)->in = &get_DR_CORE_SERVER_ANNOUNCE_RSP; + ((DR_CORE_SERVER_ANNOUNCE_RSP *)res)->out = &send_DR_CORE_SERVER_ANNOUNCE_RSP; + construct_DR_CORE_SERVER_ANNOUNCE_RSP(res); + } + else if (!g_strcasecmp(cname,"DR_CORE_CLIENT_NAME_REQ")) { + res = (void *)g_malloc(sizeof(DR_CORE_CLIENT_NAME_REQ),1); + ((DR_CORE_CLIENT_NAME_REQ *)res)->Header.out = &send_RDPDR_HEADER; + ((DR_CORE_CLIENT_NAME_REQ *)res)->Header.in = &get_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_CORE_CLIENT_NAME_REQ *)res)->Header)); + ((DR_CORE_CLIENT_NAME_REQ *)res)->__destructor = &destroy_DR_CORE_CLIENT_NAME_REQ; + ((DR_CORE_CLIENT_NAME_REQ *)res)->in = &get_DR_CORE_CLIENT_NAME_REQ; + ((DR_CORE_CLIENT_NAME_REQ *)res)->out = &send_DR_CORE_CLIENT_NAME_REQ; + construct_DR_CORE_CLIENT_NAME_REQ(res); + } + else if (!g_strcasecmp(cname,"DR_CORE_SERVER_CLIENTID_CONFIRM")) { + res = (void *)g_malloc(sizeof(DR_CORE_SERVER_CLIENTID_CONFIRM),1); + ((DR_CORE_SERVER_CLIENTID_CONFIRM *)res)->Header.out = &send_RDPDR_HEADER; + ((DR_CORE_SERVER_CLIENTID_CONFIRM *)res)->Header.in = &get_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_CORE_SERVER_CLIENTID_CONFIRM *)res)->Header)); + ((DR_CORE_SERVER_CLIENTID_CONFIRM *)res)->__destructor = &destroy_DR_CORE_SERVER_CLIENTID_CONFIRM; + ((DR_CORE_SERVER_CLIENTID_CONFIRM *)res)->in = &get_DR_CORE_SERVER_CLIENTID_CONFIRM; + ((DR_CORE_SERVER_CLIENTID_CONFIRM *)res)->out = &send_DR_CORE_SERVER_CLIENTID_CONFIRM; + construct_DR_CORE_SERVER_CLIENTID_CONFIRM(res); + } + else if (!g_strcasecmp(cname,"DR_CORE_CAPABILITY_REQ") || !g_strcasecmp(cname,"DR_CORE_CAPABILITY_RSP")) { + res = (void *)g_malloc(sizeof(DR_CORE_CAPABILITY_REQ),1); + ((DR_CORE_CAPABILITY_REQ *)res)->Header.out = &send_RDPDR_HEADER; + ((DR_CORE_CAPABILITY_REQ *)res)->Header.in = &get_RDPDR_HEADER; + ((DR_CORE_CAPABILITY_REQ *)res)->Header.Component = RDPDR_CTYP_CORE; + ((DR_CORE_CAPABILITY_REQ *)res)->Header.PacketId = PAKID_CORE_SERVER_CAPABILITY; + construct_RDPDR_HEADER(&(((DR_CORE_CAPABILITY_REQ *)res)->Header)); + ((DR_CORE_CAPABILITY_REQ *)res)->__destructor = &destroy_DR_CORE_CAPABILITY_REQ; + ((DR_CORE_CAPABILITY_REQ *)res)->in = &get_DR_CORE_CAPABILITY_REQ; + ((DR_CORE_CAPABILITY_REQ *)res)->out = &send_DR_CORE_CAPABILITY_REQ; + construct_DR_CORE_CAPABILITY_REQ(res); + } + else if (!g_strcasecmp(cname,"GENERAL_CAPS_SET")) { + res = (void *)g_malloc(sizeof(GENERAL_CAPS_SET),1); + ((GENERAL_CAPS_SET *)res)->Header.out = &send_CAPABILITY_HEADER; + ((GENERAL_CAPS_SET *)res)->Header.in = &get_CAPABILITY_HEADER; + ((GENERAL_CAPS_SET *)res)->Header.CapabilityType = GENERAL_CAPABILITY_VERSION_02; + construct_CAPABILITY_HEADER(&(((GENERAL_CAPS_SET *)res)->Header)); + ((GENERAL_CAPS_SET *)res)->protocolMajorVersion = 0x0001; + ((GENERAL_CAPS_SET *)res)->protocolMinorVersion = 0x000C; + ((GENERAL_CAPS_SET *)res)->ioCode1 = RDPDR_IRP_MJ_CREATE | RDPDR_IRP_MJ_CLEANUP | RDPDR_IRP_MJ_CLOSE | RDPDR_IRP_MJ_READ | RDPDR_IRP_MJ_WRITE | RDPDR_IRP_MJ_FLUSH_BUFFERS | RDPDR_IRP_MJ_SHUTDOWN | RDPDR_IRP_MJ_DEVICE_CONTROL | RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION | RDPDR_IRP_MJ_SET_VOLUME_INFORMATION | RDPDR_IRP_MJ_QUERY_INFORMATION | RDPDR_IRP_MJ_SET_INFORMATION | RDPDR_IRP_MJ_DIRECTORY_CONTROL | RDPDR_IRP_MJ_LOCK_CONTROL; + ((GENERAL_CAPS_SET *)res)->extendedPDU = RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | RDPDR_USER_LOGGEDON_PDU; + ((GENERAL_CAPS_SET *)res)->extraFlags1 = ENABLE_ASYNCIO; + ((GENERAL_CAPS_SET *)res)->__destructor = &destroy_GENERAL_CAPS_SET; + ((GENERAL_CAPS_SET *)res)->in = &get_GENERAL_CAPS_SET; + ((GENERAL_CAPS_SET *)res)->out = &send_GENERAL_CAPS_SET; + construct_GENERAL_CAPS_SET(res); + } + else if (!g_strcasecmp(cname,"PRINTER_CAPS_SET")) { + res = (void *)g_malloc(sizeof(PRINTER_CAPS_SET),1); + ((PRINTER_CAPS_SET *)res)->Header.out = &send_CAPABILITY_HEADER; + ((PRINTER_CAPS_SET *)res)->Header.in = &get_CAPABILITY_HEADER; + construct_CAPABILITY_HEADER(&(((PRINTER_CAPS_SET *)res)->Header)); + ((PRINTER_CAPS_SET *)res)->__destructor = &destroy_PRINTER_CAPS_SET; + ((PRINTER_CAPS_SET *)res)->in = &get_PRINTER_CAPS_SET; + ((PRINTER_CAPS_SET *)res)->out = &send_PRINTER_CAPS_SET; + construct_PRINTER_CAPS_SET(res); + } + else if (!g_strcasecmp(cname,"PORT_CAPS_SET")) { + res = (void *)g_malloc(sizeof(PORT_CAPS_SET),1); + ((PORT_CAPS_SET *)res)->Header.out = &send_CAPABILITY_HEADER; + ((PORT_CAPS_SET *)res)->Header.in = &get_CAPABILITY_HEADER; + construct_CAPABILITY_HEADER(&(((PORT_CAPS_SET *)res)->Header)); + ((PORT_CAPS_SET *)res)->__destructor = &destroy_PORT_CAPS_SET; + ((PORT_CAPS_SET *)res)->in = &get_PORT_CAPS_SET; + ((PORT_CAPS_SET *)res)->out = &send_PORT_CAPS_SET; + construct_PORT_CAPS_SET(res); + } + else if (!g_strcasecmp(cname,"DRIVE_CAPS_SET")) { + res = (void *)g_malloc(sizeof(DRIVE_CAPS_SET),1); + ((DRIVE_CAPS_SET *)res)->Header.out = &send_CAPABILITY_HEADER; + ((DRIVE_CAPS_SET *)res)->Header.in = &get_CAPABILITY_HEADER; + construct_CAPABILITY_HEADER(&(((DRIVE_CAPS_SET *)res)->Header)); + ((DRIVE_CAPS_SET *)res)->__destructor = &destroy_DRIVE_CAPS_SET; + ((DRIVE_CAPS_SET *)res)->in = &get_DRIVE_CAPS_SET; + ((DRIVE_CAPS_SET *)res)->out = &send_DRIVE_CAPS_SET; + construct_DRIVE_CAPS_SET(res); + } + else if (!g_strcasecmp(cname,"SMARTCARD_CAPS_SET")) { + res = (void *)g_malloc(sizeof(SMARTCARD_CAPS_SET),1); + ((SMARTCARD_CAPS_SET *)res)->Header.out = &send_CAPABILITY_HEADER; + ((SMARTCARD_CAPS_SET *)res)->Header.in = &get_CAPABILITY_HEADER; + construct_CAPABILITY_HEADER(&(((SMARTCARD_CAPS_SET *)res)->Header)); + ((SMARTCARD_CAPS_SET *)res)->__destructor = &destroy_SMARTCARD_CAPS_SET; + ((SMARTCARD_CAPS_SET *)res)->in = &get_SMARTCARD_CAPS_SET; + ((SMARTCARD_CAPS_SET *)res)->out = &send_SMARTCARD_CAPS_SET; + construct_SMARTCARD_CAPS_SET(res); + } + else if (!g_strcasecmp(cname,"DR_CORE_DEVICELIST_ANNOUNCE_REQ")) { + res = (void *)g_malloc(sizeof(DR_CORE_DEVICELIST_ANNOUNCE_REQ),1); + ((DR_CORE_DEVICELIST_ANNOUNCE_REQ *)res)->Header.out = &send_RDPDR_HEADER; + ((DR_CORE_DEVICELIST_ANNOUNCE_REQ *)res)->Header.in = &get_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_CORE_DEVICELIST_ANNOUNCE_REQ *)res)->Header)); + ((DR_CORE_DEVICELIST_ANNOUNCE_REQ *)res)->__destructor = &destroy_DR_CORE_DEVICELIST_ANNOUNCE_REQ; + ((DR_CORE_DEVICELIST_ANNOUNCE_REQ *)res)->in = &get_DR_CORE_DEVICELIST_ANNOUNCE_REQ; + ((DR_CORE_DEVICELIST_ANNOUNCE_REQ *)res)->out = &send_DR_CORE_DEVICELIST_ANNOUNCE_REQ; + construct_DR_CORE_DEVICELIST_ANNOUNCE_REQ(res); + } + else if (!g_strcasecmp(cname,"DR_DEVICELIST_ANNOUNCE")) { + res = (void *)g_malloc(sizeof(DR_DEVICELIST_ANNOUNCE),1); + ((DR_DEVICELIST_ANNOUNCE *)res)->Header.out = &send_RDPDR_HEADER; + ((DR_DEVICELIST_ANNOUNCE *)res)->Header.in = &get_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DEVICELIST_ANNOUNCE *)res)->Header)); + ((DR_DEVICELIST_ANNOUNCE *)res)->__destructor = &destroy_DR_DEVICELIST_ANNOUNCE; + ((DR_DEVICELIST_ANNOUNCE *)res)->in = &get_DR_DEVICELIST_ANNOUNCE; + ((DR_DEVICELIST_ANNOUNCE *)res)->out = &send_DR_DEVICELIST_ANNOUNCE; + construct_DR_DEVICELIST_ANNOUNCE(res); + } + else if (!g_strcasecmp(cname,"DR_DEVICELIST_REMOVE")) { + res = (void *)g_malloc(sizeof(DR_DEVICELIST_REMOVE),1); + ((DR_DEVICELIST_REMOVE *)res)->Header.out = &send_RDPDR_HEADER; + ((DR_DEVICELIST_REMOVE *)res)->Header.in = &get_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DEVICELIST_REMOVE *)res)->Header)); + ((DR_DEVICELIST_REMOVE *)res)->__destructor = &destroy_DR_DEVICELIST_REMOVE; + ((DR_DEVICELIST_REMOVE *)res)->in = &get_DR_DEVICELIST_REMOVE; + ((DR_DEVICELIST_REMOVE *)res)->out = &send_DR_DEVICELIST_REMOVE; + construct_DR_DEVICELIST_REMOVE(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_CORE_DEVICE_IOREQUEST")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_CORE_DEVICE_IOREQUEST),1); + ((DR_DRIVE_CORE_DEVICE_IOREQUEST *)res)->__destructor = &destroy_DR_DRIVE_CORE_DEVICE_IOREQUEST; + construct_DR_DRIVE_CORE_DEVICE_IOREQUEST(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_CREATE_REQ")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_CREATE_REQ),1); + ((DR_DRIVE_CREATE_REQ *)res)->DeviceCreateRequest.DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_CREATE_REQ *)res)->DeviceCreateRequest.DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_CREATE_REQ *)res)->DeviceCreateRequest.DeviceIoRequest.Header)); + ((DR_DRIVE_CREATE_REQ *)res)->DeviceCreateRequest.DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + ((DR_DRIVE_CREATE_REQ *)res)->DeviceCreateRequest.DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + construct_DR_CREATE_REQ(&(((DR_DRIVE_CREATE_REQ *)res)->DeviceCreateRequest)); + ((DR_DRIVE_CREATE_REQ *)res)->DeviceCreateRequest.in = &get_DR_CREATE_REQ; + ((DR_DRIVE_CREATE_REQ *)res)->DeviceCreateRequest.out = &send_DR_CREATE_REQ; + construct_DR_CREATE_REQ(&(((DR_DRIVE_CREATE_REQ *)res)->DeviceCreateRequest)); + ((DR_DRIVE_CREATE_REQ *)res)->__destructor = &destroy_DR_DRIVE_CREATE_REQ; + ((DR_DRIVE_CREATE_REQ *)res)->in = &get_DR_DRIVE_CREATE_REQ; + ((DR_DRIVE_CREATE_REQ *)res)->out = &send_DR_DRIVE_CREATE_REQ; + construct_DR_DRIVE_CREATE_REQ(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_CLOSE_REQ")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_CLOSE_REQ),1); + ((DR_DRIVE_CLOSE_REQ *)res)->DeviceCloseRequest.DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_CLOSE_REQ *)res)->DeviceCloseRequest.DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_CLOSE_REQ *)res)->DeviceCloseRequest.DeviceIoRequest.Header)); + ((DR_DRIVE_CLOSE_REQ *)res)->DeviceCloseRequest.DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + ((DR_DRIVE_CLOSE_REQ *)res)->DeviceCloseRequest.DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + construct_DR_CLOSE_REQ(&(((DR_DRIVE_CLOSE_REQ *)res)->DeviceCloseRequest)); + ((DR_DRIVE_CLOSE_REQ *)res)->DeviceCloseRequest.in = &get_DR_CLOSE_REQ; + ((DR_DRIVE_CLOSE_REQ *)res)->DeviceCloseRequest.out = &send_DR_CLOSE_REQ; + construct_DR_CLOSE_REQ(&(((DR_DRIVE_CLOSE_REQ *)res)->DeviceCloseRequest)); + ((DR_DRIVE_CLOSE_REQ *)res)->__destructor = &destroy_DR_DRIVE_CLOSE_REQ; + ((DR_DRIVE_CLOSE_REQ *)res)->in = &get_DR_DRIVE_CLOSE_REQ; + ((DR_DRIVE_CLOSE_REQ *)res)->out = &send_DR_DRIVE_CLOSE_REQ; + construct_DR_DRIVE_CLOSE_REQ(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_READ_REQ")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_READ_REQ),1); + ((DR_DRIVE_READ_REQ *)res)->DeviceReadRequest.DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_READ_REQ *)res)->DeviceReadRequest.DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_READ_REQ *)res)->DeviceReadRequest.DeviceIoRequest.Header)); + ((DR_DRIVE_READ_REQ *)res)->DeviceReadRequest.DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + ((DR_DRIVE_READ_REQ *)res)->DeviceReadRequest.DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + construct_DR_READ_REQ(&(((DR_DRIVE_READ_REQ *)res)->DeviceReadRequest)); + ((DR_DRIVE_READ_REQ *)res)->DeviceReadRequest.in = &get_DR_READ_REQ; + ((DR_DRIVE_READ_REQ *)res)->DeviceReadRequest.out = &send_DR_READ_REQ; + construct_DR_READ_REQ(&(((DR_DRIVE_READ_REQ *)res)->DeviceReadRequest)); + ((DR_DRIVE_READ_REQ *)res)->__destructor = &destroy_DR_DRIVE_READ_REQ; + ((DR_DRIVE_READ_REQ *)res)->out = &send_DR_DRIVE_READ_REQ; + ((DR_DRIVE_READ_REQ *)res)->in = &get_DR_DRIVE_READ_REQ; + construct_DR_DRIVE_READ_REQ(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_WRITE_REQ")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_WRITE_REQ),1); + ((DR_DRIVE_WRITE_REQ *)res)->DeviceWriteRequest.DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_WRITE_REQ *)res)->DeviceWriteRequest.DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_WRITE_REQ *)res)->DeviceWriteRequest.DeviceIoRequest.Header)); + ((DR_DRIVE_WRITE_REQ *)res)->DeviceWriteRequest.DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + ((DR_DRIVE_WRITE_REQ *)res)->DeviceWriteRequest.DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + construct_DR_WRITE_REQ(&(((DR_DRIVE_WRITE_REQ *)res)->DeviceWriteRequest)); + ((DR_DRIVE_WRITE_REQ *)res)->DeviceWriteRequest.in = &get_DR_WRITE_REQ; + ((DR_DRIVE_WRITE_REQ *)res)->DeviceWriteRequest.out = &send_DR_WRITE_REQ; + construct_DR_WRITE_REQ(&(((DR_DRIVE_WRITE_REQ *)res)->DeviceWriteRequest)); + ((DR_DRIVE_WRITE_REQ *)res)->__destructor = &destroy_DR_DRIVE_WRITE_REQ; + ((DR_DRIVE_WRITE_REQ *)res)->out = &send_DR_DRIVE_WRITE_REQ; + ((DR_DRIVE_WRITE_REQ *)res)->in = &get_DR_DRIVE_WRITE_REQ; + construct_DR_DRIVE_WRITE_REQ(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_CONTROL_REQ")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_CONTROL_REQ),1); + ((DR_DRIVE_CONTROL_REQ *)res)->Header.DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_CONTROL_REQ *)res)->Header.DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_CONTROL_REQ *)res)->Header.DeviceIoRequest.Header)); + ((DR_DRIVE_CONTROL_REQ *)res)->Header.DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + ((DR_DRIVE_CONTROL_REQ *)res)->Header.DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + construct_DR_DEVICE_IOREQUEST(&(((DR_DRIVE_CONTROL_REQ *)res)->Header.DeviceIoRequest)); + ((DR_DRIVE_CONTROL_REQ *)res)->Header.in = &get_DR_CONTROL_REQ; + ((DR_DRIVE_CONTROL_REQ *)res)->Header.out = &send_DR_CONTROL_REQ; + construct_DR_CONTROL_REQ(&(((DR_DRIVE_CONTROL_REQ *)res)->Header)); + ((DR_DRIVE_CONTROL_REQ *)res)->__destructor = &destroy_DR_DRIVE_CONTROL_REQ; + ((DR_DRIVE_CONTROL_REQ *)res)->out = &send_DR_DRIVE_CONTROL_REQ; + ((DR_DRIVE_CONTROL_REQ *)res)->in = &get_DR_DRIVE_CONTROL_REQ; + construct_DR_DRIVE_CONTROL_REQ(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ),1); + ((DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ *)res)->DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ *)res)->DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ *)res)->DeviceIoRequest.Header)); + ((DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ *)res)->DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + ((DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ *)res)->DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + construct_DR_DEVICE_IOREQUEST(&(((DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ *)res)->DeviceIoRequest)); + ((DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ *)res)->__destructor = &destroy_DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ; + ((DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ *)res)->out = &send_DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ; + ((DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ *)res)->in = &get_DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ; + construct_DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_SET_VOLUME_INFORMATION_REQ")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_SET_VOLUME_INFORMATION_REQ),1); + ((DR_DRIVE_SET_VOLUME_INFORMATION_REQ *)res)->DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_SET_VOLUME_INFORMATION_REQ *)res)->DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_SET_VOLUME_INFORMATION_REQ *)res)->DeviceIoRequest.Header)); + ((DR_DRIVE_SET_VOLUME_INFORMATION_REQ *)res)->DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + ((DR_DRIVE_SET_VOLUME_INFORMATION_REQ *)res)->DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + construct_DR_DEVICE_IOREQUEST(&(((DR_DRIVE_SET_VOLUME_INFORMATION_REQ *)res)->DeviceIoRequest)); + ((DR_DRIVE_SET_VOLUME_INFORMATION_REQ *)res)->__destructor = &destroy_DR_DRIVE_SET_VOLUME_INFORMATION_REQ; + ((DR_DRIVE_SET_VOLUME_INFORMATION_REQ *)res)->out = &send_DR_DRIVE_SET_VOLUME_INFORMATION_REQ; + ((DR_DRIVE_SET_VOLUME_INFORMATION_REQ *)res)->in = &get_DR_DRIVE_SET_VOLUME_INFORMATION_REQ; + construct_DR_DRIVE_SET_VOLUME_INFORMATION_REQ(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_QUERY_INFORMATION_REQ")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_QUERY_INFORMATION_REQ),1); + ((DR_DRIVE_QUERY_INFORMATION_REQ *)res)->DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_QUERY_INFORMATION_REQ *)res)->DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_QUERY_INFORMATION_REQ *)res)->DeviceIoRequest.Header)); + ((DR_DRIVE_QUERY_INFORMATION_REQ *)res)->DeviceIoRequest.MajorFunction = IRP_MJ_DIRECTORY_CONTROL; + ((DR_DRIVE_QUERY_INFORMATION_REQ *)res)->DeviceIoRequest.MinorFunction = IRP_MN_QUERY_DIRECTORY; + ((DR_DRIVE_QUERY_INFORMATION_REQ *)res)->DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + ((DR_DRIVE_QUERY_INFORMATION_REQ *)res)->DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + construct_DR_DEVICE_IOREQUEST(&(((DR_DRIVE_QUERY_INFORMATION_REQ *)res)->DeviceIoRequest)); + ((DR_DRIVE_QUERY_INFORMATION_REQ *)res)->FsInformationClass = FileDirectoryInformation; + ((DR_DRIVE_QUERY_INFORMATION_REQ *)res)->__destructor = &destroy_DR_DRIVE_QUERY_INFORMATION_REQ; + ((DR_DRIVE_QUERY_INFORMATION_REQ *)res)->in = &get_DR_DRIVE_QUERY_INFORMATION_REQ; + ((DR_DRIVE_QUERY_INFORMATION_REQ *)res)->out = &send_DR_DRIVE_QUERY_INFORMATION_REQ; + construct_DR_DRIVE_QUERY_INFORMATION_REQ(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_SET_INFORMATION_REQ")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_SET_INFORMATION_REQ),1); + ((DR_DRIVE_SET_INFORMATION_REQ *)res)->DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_SET_INFORMATION_REQ *)res)->DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_SET_INFORMATION_REQ *)res)->DeviceIoRequest.Header)); + ((DR_DRIVE_SET_INFORMATION_REQ *)res)->DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + ((DR_DRIVE_SET_INFORMATION_REQ *)res)->DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + construct_DR_DEVICE_IOREQUEST(&(((DR_DRIVE_SET_INFORMATION_REQ *)res)->DeviceIoRequest)); + ((DR_DRIVE_SET_INFORMATION_REQ *)res)->__destructor = &destroy_DR_DRIVE_SET_INFORMATION_REQ; + ((DR_DRIVE_SET_INFORMATION_REQ *)res)->in = &get_DR_DRIVE_SET_INFORMATION_REQ; + ((DR_DRIVE_SET_INFORMATION_REQ *)res)->out = &send_DR_DRIVE_SET_INFORMATION_REQ; + construct_DR_DRIVE_SET_INFORMATION_REQ(res); + } + else if (!g_strcasecmp(cname,"RDP_FILE_RENAME_INFORMATION")) { + res = (void *)g_malloc(sizeof(RDP_FILE_RENAME_INFORMATION),1); + construct_RDP_FILE_RENAME_INFORMATION(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_QUERY_DIRECTORY_REQ")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_QUERY_DIRECTORY_REQ),1); + ((DR_DRIVE_QUERY_DIRECTORY_REQ *)res)->DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_QUERY_DIRECTORY_REQ *)res)->DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_QUERY_DIRECTORY_REQ *)res)->DeviceIoRequest.Header)); + ((DR_DRIVE_QUERY_DIRECTORY_REQ *)res)->DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + ((DR_DRIVE_QUERY_DIRECTORY_REQ *)res)->DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + construct_DR_DEVICE_IOREQUEST(&(((DR_DRIVE_QUERY_DIRECTORY_REQ *)res)->DeviceIoRequest)); + ((DR_DRIVE_QUERY_DIRECTORY_REQ *)res)->__destructor = &destroy_DR_DRIVE_QUERY_DIRECTORY_REQ; + ((DR_DRIVE_QUERY_DIRECTORY_REQ *)res)->in = &get_DR_DRIVE_QUERY_DIRECTORY_REQ; + ((DR_DRIVE_QUERY_DIRECTORY_REQ *)res)->out = &send_DR_DRIVE_QUERY_DIRECTORY_REQ; + construct_DR_DRIVE_QUERY_DIRECTORY_REQ(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ),1); + ((DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ *)res)->DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ *)res)->DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ *)res)->DeviceIoRequest.Header)); + ((DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ *)res)->DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + ((DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ *)res)->DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + construct_DR_DEVICE_IOREQUEST(&(((DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ *)res)->DeviceIoRequest)); + ((DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ *)res)->__destructor = &destroy_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ; + ((DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ *)res)->in = &get_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ; + ((DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ *)res)->out = &send_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ; + construct_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_LOCK_REQ")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_LOCK_REQ),1); + ((DR_DRIVE_LOCK_REQ *)res)->DeviceIoRequest.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_LOCK_REQ *)res)->DeviceIoRequest.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_LOCK_REQ *)res)->DeviceIoRequest.Header)); + ((DR_DRIVE_LOCK_REQ *)res)->DeviceIoRequest.in = &get_DR_DEVICE_IOREQUEST; + ((DR_DRIVE_LOCK_REQ *)res)->DeviceIoRequest.out = &send_DR_DEVICE_IOREQUEST; + construct_DR_DEVICE_IOREQUEST(&(((DR_DRIVE_LOCK_REQ *)res)->DeviceIoRequest)); + ((DR_DRIVE_LOCK_REQ *)res)->__destructor = &destroy_DR_DRIVE_LOCK_REQ; + ((DR_DRIVE_LOCK_REQ *)res)->in = &get_DR_DRIVE_LOCK_REQ; + ((DR_DRIVE_LOCK_REQ *)res)->out = &send_DR_DRIVE_LOCK_REQ; + construct_DR_DRIVE_LOCK_REQ(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_CORE_DEVICE_IOCOMPLETION")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_CORE_DEVICE_IOCOMPLETION),1); + ((DR_DRIVE_CORE_DEVICE_IOCOMPLETION *)res)->__destructor = &destroy_DR_DRIVE_CORE_DEVICE_IOCOMPLETION; + construct_DR_DRIVE_CORE_DEVICE_IOCOMPLETION(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_CREATE_RSP")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_CREATE_RSP),1); + ((DR_DRIVE_CREATE_RSP *)res)->DeviceCreateResponse.DeviceIoReply.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_CREATE_RSP *)res)->DeviceCreateResponse.DeviceIoReply.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_CREATE_RSP *)res)->DeviceCreateResponse.DeviceIoReply.Header)); + ((DR_DRIVE_CREATE_RSP *)res)->DeviceCreateResponse.DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + ((DR_DRIVE_CREATE_RSP *)res)->DeviceCreateResponse.DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + construct_DR_DEVICE_IOCOMPLETION(&(((DR_DRIVE_CREATE_RSP *)res)->DeviceCreateResponse.DeviceIoReply)); + ((DR_DRIVE_CREATE_RSP *)res)->DeviceCreateResponse.in = &get_DR_CREATE_RSP; + ((DR_DRIVE_CREATE_RSP *)res)->DeviceCreateResponse.out = &send_DR_CREATE_RSP; + construct_DR_CREATE_RSP(&(((DR_DRIVE_CREATE_RSP *)res)->DeviceCreateResponse)); + ((DR_DRIVE_CREATE_RSP *)res)->__destructor = &destroy_DR_DRIVE_CREATE_RSP; + ((DR_DRIVE_CREATE_RSP *)res)->in = &get_DR_DRIVE_CREATE_RSP; + ((DR_DRIVE_CREATE_RSP *)res)->out = &send_DR_DRIVE_CREATE_RSP; + construct_DR_DRIVE_CREATE_RSP(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_CLOSE_RSP")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_CLOSE_RSP),1); + ((DR_DRIVE_CLOSE_RSP *)res)->DeviceCloseResponse.DeviceIoReply.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_CLOSE_RSP *)res)->DeviceCloseResponse.DeviceIoReply.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_CLOSE_RSP *)res)->DeviceCloseResponse.DeviceIoReply.Header)); + ((DR_DRIVE_CLOSE_RSP *)res)->DeviceCloseResponse.DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + ((DR_DRIVE_CLOSE_RSP *)res)->DeviceCloseResponse.DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + construct_DR_DEVICE_IOCOMPLETION(&(((DR_DRIVE_CLOSE_RSP *)res)->DeviceCloseResponse.DeviceIoReply)); + ((DR_DRIVE_CLOSE_RSP *)res)->DeviceCloseResponse.in = &get_DR_CLOSE_RSP; + ((DR_DRIVE_CLOSE_RSP *)res)->DeviceCloseResponse.out = &send_DR_CLOSE_RSP; + construct_DR_CLOSE_RSP(&(((DR_DRIVE_CLOSE_RSP *)res)->DeviceCloseResponse)); + ((DR_DRIVE_CLOSE_RSP *)res)->__destructor = &destroy_DR_DRIVE_CLOSE_RSP; + ((DR_DRIVE_CLOSE_RSP *)res)->in = &get_DR_DRIVE_CLOSE_RSP; + ((DR_DRIVE_CLOSE_RSP *)res)->out = &send_DR_DRIVE_CLOSE_RSP; + construct_DR_DRIVE_CLOSE_RSP(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP),1); + ((DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP *)res)->DeviceIoReply.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP *)res)->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP *)res)->DeviceIoReply.Header)); + ((DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP *)res)->DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + ((DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP *)res)->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + construct_DR_DEVICE_IOCOMPLETION(&(((DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP *)res)->DeviceIoReply)); + ((DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP *)res)->__destructor = &destroy_DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP; + ((DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP *)res)->in = &get_DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP; + ((DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP *)res)->out = &send_DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP; + construct_DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_SET_VOLUME_INFORMATION_RSP")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_SET_VOLUME_INFORMATION_RSP),1); + ((DR_DRIVE_SET_VOLUME_INFORMATION_RSP *)res)->DeviceIoReply.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_SET_VOLUME_INFORMATION_RSP *)res)->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_SET_VOLUME_INFORMATION_RSP *)res)->DeviceIoReply.Header)); + ((DR_DRIVE_SET_VOLUME_INFORMATION_RSP *)res)->DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + ((DR_DRIVE_SET_VOLUME_INFORMATION_RSP *)res)->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + construct_DR_DEVICE_IOCOMPLETION(&(((DR_DRIVE_SET_VOLUME_INFORMATION_RSP *)res)->DeviceIoReply)); + ((DR_DRIVE_SET_VOLUME_INFORMATION_RSP *)res)->__destructor = &destroy_DR_DRIVE_SET_VOLUME_INFORMATION_RSP; + ((DR_DRIVE_SET_VOLUME_INFORMATION_RSP *)res)->in = &get_DR_DRIVE_SET_VOLUME_INFORMATION_RSP; + ((DR_DRIVE_SET_VOLUME_INFORMATION_RSP *)res)->out = &send_DR_DRIVE_SET_VOLUME_INFORMATION_RSP; + construct_DR_DRIVE_SET_VOLUME_INFORMATION_RSP(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_QUERY_INFORMATION_RSP")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_QUERY_INFORMATION_RSP),1); + ((DR_DRIVE_QUERY_INFORMATION_RSP *)res)->DeviceIoReply.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_QUERY_INFORMATION_RSP *)res)->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_QUERY_INFORMATION_RSP *)res)->DeviceIoReply.Header)); + ((DR_DRIVE_QUERY_INFORMATION_RSP *)res)->DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + ((DR_DRIVE_QUERY_INFORMATION_RSP *)res)->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + construct_DR_DEVICE_IOCOMPLETION(&(((DR_DRIVE_QUERY_INFORMATION_RSP *)res)->DeviceIoReply)); + ((DR_DRIVE_QUERY_INFORMATION_RSP *)res)->__destructor = &destroy_DR_DRIVE_QUERY_INFORMATION_RSP; + ((DR_DRIVE_QUERY_INFORMATION_RSP *)res)->in = &get_DR_DRIVE_QUERY_INFORMATION_RSP; + ((DR_DRIVE_QUERY_INFORMATION_RSP *)res)->out = &send_DR_DRIVE_QUERY_INFORMATION_RSP; + construct_DR_DRIVE_QUERY_INFORMATION_RSP(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_QUERY_DIRECTORY_RSP")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_QUERY_DIRECTORY_RSP),1); + ((DR_DRIVE_QUERY_DIRECTORY_RSP *)res)->DeviceIoReply.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_QUERY_DIRECTORY_RSP *)res)->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_QUERY_DIRECTORY_RSP *)res)->DeviceIoReply.Header)); + ((DR_DRIVE_QUERY_DIRECTORY_RSP *)res)->DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + ((DR_DRIVE_QUERY_DIRECTORY_RSP *)res)->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + construct_DR_DEVICE_IOCOMPLETION(&(((DR_DRIVE_QUERY_DIRECTORY_RSP *)res)->DeviceIoReply)); + ((DR_DRIVE_QUERY_DIRECTORY_RSP *)res)->__destructor = &destroy_DR_DRIVE_QUERY_DIRECTORY_RSP; + ((DR_DRIVE_QUERY_DIRECTORY_RSP *)res)->in = &get_DR_DRIVE_QUERY_DIRECTORY_RSP; + ((DR_DRIVE_QUERY_DIRECTORY_RSP *)res)->out = &send_DR_DRIVE_QUERY_DIRECTORY_RSP; + construct_DR_DRIVE_QUERY_DIRECTORY_RSP(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP),1); + ((DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP *)res)->DeviceIoReply.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP *)res)->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP *)res)->DeviceIoReply.Header)); + ((DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP *)res)->DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + ((DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP *)res)->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + construct_DR_DEVICE_IOCOMPLETION(&(((DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP *)res)->DeviceIoReply)); + ((DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP *)res)->__destructor = &destroy_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP; + ((DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP *)res)->in = &get_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP; + ((DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP *)res)->out = &send_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP; + construct_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP(res); + } + else if (!g_strcasecmp(cname,"DR_DRIVE_LOCK_RSP")) { + res = (void *)g_malloc(sizeof(DR_DRIVE_LOCK_RSP),1); + ((DR_DRIVE_LOCK_RSP *)res)->DeviceIoReply.Header.in = &get_RDPDR_HEADER; + ((DR_DRIVE_LOCK_RSP *)res)->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_DRIVE_LOCK_RSP *)res)->DeviceIoReply.Header)); + ((DR_DRIVE_LOCK_RSP *)res)->DeviceIoReply.in = &get_DR_DEVICE_IOCOMPLETION; + ((DR_DRIVE_LOCK_RSP *)res)->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + construct_DR_DEVICE_IOCOMPLETION(&(((DR_DRIVE_LOCK_RSP *)res)->DeviceIoReply)); + ((DR_DRIVE_LOCK_RSP *)res)->__destructor = &destroy_DR_DRIVE_LOCK_RSP; + ((DR_DRIVE_LOCK_RSP *)res)->in = &get_DR_DRIVE_LOCK_RSP; + ((DR_DRIVE_LOCK_RSP *)res)->out = &send_DR_DRIVE_LOCK_RSP; + construct_DR_DRIVE_LOCK_RSP(res); + } + else if (!g_strcasecmp(cname,"DR_CORE_USER_LOGGEDON")) { + res = (void *)g_malloc(sizeof(DR_CORE_USER_LOGGEDON),1); + ((DR_CORE_USER_LOGGEDON *)res)->Header.in = &get_RDPDR_HEADER; + ((DR_CORE_USER_LOGGEDON *)res)->Header.out = &send_RDPDR_HEADER; + construct_RDPDR_HEADER(&(((DR_CORE_USER_LOGGEDON *)res)->Header)); + ((DR_CORE_USER_LOGGEDON *)res)->__destructor = &destroy_DR_CORE_USER_LOGGEDON; + ((DR_CORE_USER_LOGGEDON *)res)->in = &get_DR_CORE_USER_LOGGEDON; + ((DR_CORE_USER_LOGGEDON *)res)->out = &send_DR_CORE_USER_LOGGEDON; + construct_DR_CORE_USER_LOGGEDON(res); + } + else if (!g_strcasecmp(cname,"DYNVC_CAPS_VERSION1")) { + res = (void *)g_malloc(sizeof(DYNVC_CAPS_VERSION1),1); + construct_DYNVC_CAPS_VERSION1(res); + } + else if (!g_strcasecmp(cname,"DYNVC_CAPS_VERSION2")) { + res = (void *)g_malloc(sizeof(DYNVC_CAPS_VERSION2),1); + construct_DYNVC_CAPS_VERSION2(res); + } + else if (!g_strcasecmp(cname,"DYNVC_CAPS_RSP")) { + res = (void *)g_malloc(sizeof(DYNVC_CAPS_RSP),1); + construct_DYNVC_CAPS_RSP(res); + } + else if (!g_strcasecmp(cname,"DYNVC_CREATE_REQ")) { + res = (void *)g_malloc(sizeof(DYNVC_CREATE_REQ) + 50,1); + construct_DYNVC_CREATE_REQ(res); + } + else if (!g_strcasecmp(cname,"DYNVC_CREATE_RSP")) { + res = (void *)g_malloc(sizeof(DYNVC_CREATE_RSP),1); + construct_DYNVC_CREATE_RSP(res); + } + else if (!g_strcasecmp(cname,"DYNVC_DATA_FIRST")) { + res = (void *)g_malloc(sizeof(DYNVC_DATA_FIRST) + 1600,1); + construct_DYNVC_DATA_FIRST(res); + } + else if (!g_strcasecmp(cname,"DYNVC_DATA")) { + res = (void *)g_malloc(sizeof(DYNVC_DATA) + 1600,1); + construct_DYNVC_DATA(res); + } + else if (!g_strcasecmp(cname,"DYNVC_CLOSE")) { + res = (void *)g_malloc(sizeof(DYNVC_CLOSE),1); + construct_DYNVC_CLOSE(res); + } + + return res; +} + +/*****************************************************************************/ +static int APP_CC setPath_DR_DRIVE_QUERY_DIRECTORY_REQ(struct _DR_DRIVE_QUERY_DIRECTORY_REQ * self, const char * pn) { + int rv = 0; + int idx = 0; + int lmt = 0; + + g_memset(self->Path,0x00,sizeof(BYTE) * 512); + lmt = g_strlen(pn); + if ((pn != NULL) && (lmt > 0)) { + if (lmt > 255) { + lmt = 255; + } + for (idx = 0; idx < lmt; idx++) { + self->Path[(idx * 2)] = pn[idx]; + } + self->PathLength = lmt * 2; + } + else { + self->PathLength = 2; + } + + return rv; +} + +int APP_CC send_MSG_SNDIN_VERSION(MSG_SNDIN_VERSION * self, struct stream * s) { + int rv = 0; + if (self == NULL || s == NULL || s->data == NULL || s->p == NULL) { + rv = -1; + } + else { + out_uint8(s, self->Header.MessageId); + out_uint32_le(s, self->Version); + } + return rv; +} + +int APP_CC get_MSG_SNDIN_VERSION(MSG_SNDIN_VERSION * self, struct stream * s) { + int rv = 0; + if (self == NULL || s == NULL || s->data == NULL || s->p == NULL) { + rv = -1; + } + else { + in_uint8(s, self->Header.MessageId); + in_uint32_le(s, self->Version); + } + return rv; +} + +int APP_CC send_MSG_SNDIN_FORMATS(MSG_SNDIN_FORMATS * self, struct stream * s) { + int rv = 0; + if (self == NULL || s == NULL || s->data == NULL || s->p == NULL) { + rv = -1; + } + else { + ptrdiff_t i = 0; + out_uint8(s, self->Header.MessageId); + out_uint32_le(s, self->NumFormats); + out_uint32_le(s, self->cbSizeFormatsPacket); + if (self->NumFormats > 0) for (i = 0; i < self->NumFormats; i++) { + AUDIO_FORMAT_REC * fmt = (AUDIO_FORMAT_REC *)(&(self->SoundFormats[i])); + out_uint16_le(s, fmt->wFormatTag); + out_uint16_le(s, fmt->nChannels); + out_uint32_le(s, fmt->nSamplesPerSec); + out_uint32_le(s, fmt->nAvgBytesPerSec); + out_uint16_le(s, fmt->nBlockAlign); + out_uint16_le(s, fmt->wBitsPerSample); + out_uint16_le(s, fmt->cbSize); + if (fmt->cbSize > 0 && fmt->data != NULL) { + out_uint8a(s, fmt->data, fmt->cbSize); + } + } + } + return rv; +} + +int APP_CC get_MSG_SNDIN_FORMATS(MSG_SNDIN_FORMATS * self, struct stream * s) { + int rv = 0; + if (self == NULL || s == NULL) { + rv = -1; + } + else { + in_uint8(s, self->Header.MessageId); + in_uint32_le(s, self->NumFormats); + in_uint32_le(s, self->cbSizeFormatsPacket); + if (self->NumFormats > 0 && self->cbSizeFormatsPacket > 0) { + in_uint8a(s, self->SoundFormats, self->cbSizeFormatsPacket); + } + } + return rv; +} + +int APP_CC send_MSG_SNDIN_OPEN(MSG_SNDIN_OPEN * self, struct stream * s) { + int rv = 0; + if (self == NULL || s == NULL || s->data == NULL || s->p == NULL) { + rv = -1; + } + else { + out_uint8(s, self->Header.MessageId); + out_uint32_le(s, self->FramesPerPacket); + out_uint32_le(s, self->initialFormat); + out_uint16_le(s, self->wFormatTag); + out_uint16_le(s, self->nChannels); + out_uint32_le(s, self->nSamplesPerSec); + out_uint32_le(s, self->nAvgBytesPerSec); + out_uint16_le(s, self->nBlockAlign); + out_uint16_le(s, self->wBitsPerSample); + out_uint16_le(s, self->cbSize); + if (self->cbSize > 0) { + out_uint8a(s, self->ExtraFormatData, self->cbSize); + } + } + return rv; +} + +int APP_CC get_MSG_SNDIN_OPEN(MSG_SNDIN_OPEN * self, struct stream * s) { + int rv = 0; + if (self == NULL || s == NULL || s->data == NULL || s->p == NULL) { + rv = -1; + } + else { + in_uint8(s, self->Header.MessageId); + in_uint32_le(s, self->FramesPerPacket); + in_uint32_le(s, self->initialFormat); + in_uint16_le(s, self->wFormatTag); + in_uint16_le(s, self->nChannels); + in_uint32_le(s, self->nSamplesPerSec); + in_uint32_le(s, self->nAvgBytesPerSec); + in_uint16_le(s, self->nBlockAlign); + in_uint16_le(s, self->wBitsPerSample); + in_uint16_le(s, self->cbSize); + if (self->cbSize > 0) { + in_uint8a(s, self->ExtraFormatData, self->cbSize); + } + } + return rv; +} + +int APP_CC send_MSG_SNDIN_OPEN_REPLY(MSG_SNDIN_OPEN_REPLY * self, struct stream * s) { + int rv = 0; + if (self == NULL || s == NULL || s->data == NULL || s->p == NULL) { + rv = -1; + } + else { + out_uint8(s, self->Header.MessageId); + out_uint32_le(s, self->Result); + } + return rv; +} + +int APP_CC get_MSG_SNDIN_OPEN_REPLY(MSG_SNDIN_OPEN_REPLY * self, struct stream * s) { + int rv = 0; + if (self == NULL || s == NULL || s->data == NULL || s->p == NULL) { + rv = -1; + } + else { + in_uint8(s, self->Header.MessageId); + in_uint32_le(s, self->Result); + } + return rv; +} + +int APP_CC send_MSG_SNDIN_DATA_INCOMING(MSG_SNDIN_DATA_INCOMING * self, struct stream * s) { + int rv = 0; + if (self == NULL || s == NULL || s->data == NULL || s->p == NULL) { + rv = -1; + } + else { + out_uint8(s, self->Header.MessageId); + } + return rv; +} + +int APP_CC get_MSG_SNDIN_DATA_INCOMING(MSG_SNDIN_DATA_INCOMING * self, struct stream * s) { + int rv = 0; + if (self == NULL || s == NULL || s->data == NULL || s->p == NULL) { + rv = -1; + } + else { + in_uint8(s, self->Header.MessageId); + } + return rv; +} + +int APP_CC send_MSG_SNDIN_DATA(MSG_SNDIN_DATA * self, struct stream * s) { + int rv = 0; + if (self == NULL || s == NULL || s->data == NULL || s->p == NULL || self->len < 1) { + rv = -1; + } + else { + out_uint8(s, self->Header.MessageId); + out_uint8a(s, self->Data, self->len); + } + return rv; +} + +int APP_CC get_MSG_SNDIN_DATA(MSG_SNDIN_DATA * self, struct stream * s) { + int rv = 0; + if (self == NULL || s == NULL || s->data == NULL || s->p == NULL) { + rv = -1; + } + else { + in_uint8(s, self->Header.MessageId); + if (s->end > s->p) { + self->len = s->end - s->p; + in_uint8a(s, self->Data, self->len); + } + } + return rv; +} + +int APP_CC send_MSG_SNDIN_FORMATCHANGE(MSG_SNDIN_FORMATCHANGE * self, struct stream * s) { + int rv = 0; + if (self == NULL || s == NULL || s->data == NULL || s->p == NULL) { + rv = -1; + } + else { + out_uint8(s, self->Header.MessageId); + out_uint32_le(s, self->NewFormat); + } + return rv; +} + +int APP_CC get_MSG_SNDIN_FORMATCHANGE(MSG_SNDIN_FORMATCHANGE * self, struct stream * s) { + int rv = 0; + if (self == NULL || s == NULL || s->data == NULL || s->p == NULL) { + rv = -1; + } + else { + in_uint8(s, self->Header.MessageId); + in_uint32_le(s, self->NewFormat); + } + return rv; +} + +int APP_CC send_WAVEFORMAT_EXTENSIBLE(WAVEFORMAT_EXTENSIBLE * self, struct stream * s) { + int rv = 0; + if (self == NULL || s == NULL || s->data == NULL || s->p == NULL) { + rv = -1; + } + else { + out_uint16_le(s, self->wValidBitsPerSample); + out_uint32_le(s, self->dwChannelMask); + /* GUID */ + out_uint32_le(s, self->SubFormat.f1); + out_uint16_le(s, self->SubFormat.f2); + out_uint16_le(s, self->SubFormat.f3); + out_uint8(s, self->SubFormat.f4[0]); + out_uint8(s, self->SubFormat.f4[1]); + out_uint8(s, self->SubFormat.f4[2]); + out_uint8(s, self->SubFormat.f4[3]); + out_uint8(s, self->SubFormat.f4[4]); + out_uint8(s, self->SubFormat.f4[5]); + out_uint8(s, self->SubFormat.f4[6]); + out_uint8(s, self->SubFormat.f4[7]); + } + return rv; +} + +int APP_CC get_WAVEFORMAT_EXTENSIBLE(WAVEFORMAT_EXTENSIBLE * self, struct stream * s) { + int rv = 0; + if (self == NULL || s == NULL || s->data == NULL || s->p == NULL) { + rv = -1; + } + else { + in_uint16_le(s, self->wValidBitsPerSample); + in_uint32_le(s, self->dwChannelMask); + /* GUID */ + in_uint32_le(s, self->SubFormat.f1); + in_uint16_le(s, self->SubFormat.f2); + in_uint16_le(s, self->SubFormat.f3); + in_uint8(s, self->SubFormat.f4[0]); + in_uint8(s, self->SubFormat.f4[1]); + in_uint8(s, self->SubFormat.f4[2]); + in_uint8(s, self->SubFormat.f4[3]); + in_uint8(s, self->SubFormat.f4[4]); + in_uint8(s, self->SubFormat.f4[5]); + in_uint8(s, self->SubFormat.f4[6]); + in_uint8(s, self->SubFormat.f4[7]); + } + return rv; +} diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/rdpdr_methods.h posixrdp/posixxrdp.orig/common/rdpdr_methods.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/rdpdr_methods.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/rdpdr_methods.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,372 @@ +#if !defined(__XRDP_RDPDR_METHODS__) +#define __XRDP_RDPDR_METHODS__ + + +#include "os_calls.h" +#include "rdpdr.h" +#include "thread_calls.h" +#include "thread_macros.h" +#include "trans.h" + + + +/************************************************************************** + * + * macros + */ + +#define RDPDR_NEW(c) (c *)rdpdr_inst(#c) +#define RDPDR_FREE(itm) { \ + if (itm != NULL) { \ + if ( (*itm->__destructor) != NULL ) { \ + (*itm->__destructor)((void *)itm); \ + } \ + itm = NULL; \ + } \ +} + + + +/************************************************************************** + * + * global variables + */ + + +/************************************************************************** + * + * constructors + */ + +int APP_CC construct_RDPDR_HEADER(RDPDR_HEADER *); +int APP_CC construct_CAPABILITY_HEADER(CAPABILITY_HEADER *); +int APP_CC construct_CAPABILITY_SET(CAPABILITY_SET *); +int APP_CC construct_DEVICE_ANNOUNCE(DEVICE_ANNOUNCE *); +int APP_CC construct_DR_DEVICE_IOREQUEST(DR_DEVICE_IOREQUEST *); +int APP_CC construct_DR_CREATE_REQ(DR_CREATE_REQ *); +int APP_CC construct_DR_CLOSE_REQ(DR_CLOSE_REQ *); +int APP_CC construct_DR_READ_REQ(DR_READ_REQ *); +int APP_CC construct_DR_WRITE_REQ(DR_WRITE_REQ *); +int APP_CC construct_DR_CONTROL_REQ(DR_CONTROL_REQ *); +int APP_CC construct_DR_DEVICE_IOCOMPLETION(DR_DEVICE_IOCOMPLETION *); +int APP_CC construct_DR_CREATE_RSP(DR_CREATE_RSP *); +int APP_CC construct_DR_CLOSE_RSP(DR_CLOSE_RSP *); +int APP_CC construct_DR_READ_RSP(DR_READ_RSP *); +int APP_CC construct_DR_WRITE_RSP(DR_WRITE_RSP *); +int APP_CC construct_DR_CONTROL_RSP(DR_CONTROL_RSP *); +int APP_CC construct_RDP_LOCK_INFO(RDP_LOCK_INFO *); +int APP_CC construct_DR_CORE_DEVICE_ANNOUNCE_RSP(DR_CORE_DEVICE_ANNOUNCE_RSP *); +int APP_CC construct_DR_CORE_SERVER_ANNOUNCE_REQ(DR_CORE_SERVER_ANNOUNCE_REQ *); +int APP_CC construct_DR_CORE_SERVER_ANNOUNCE_RSP(DR_CORE_SERVER_ANNOUNCE_RSP *); +int APP_CC construct_DR_CORE_CLIENT_NAME_REQ(DR_CORE_CLIENT_NAME_REQ *); +int APP_CC construct_DR_CORE_SERVER_CLIENTID_CONFIRM(DR_CORE_SERVER_CLIENTID_CONFIRM *); +int APP_CC construct_DR_CORE_CAPABILITY_REQ(DR_CORE_CAPABILITY_REQ *); +int APP_CC construct_GENERAL_CAPS_SET(GENERAL_CAPS_SET *); +int APP_CC construct_PRINTER_CAPS_SET(PRINTER_CAPS_SET *); +int APP_CC construct_PORT_CAPS_SET(PORT_CAPS_SET *); +int APP_CC construct_DRIVE_CAPS_SET(DRIVE_CAPS_SET *); +int APP_CC construct_SMARTCARD_CAPS_SET(SMARTCARD_CAPS_SET *); +int APP_CC construct_DR_CORE_DEVICELIST_ANNOUNCE_REQ(DR_CORE_DEVICELIST_ANNOUNCE_REQ *); +int APP_CC construct_DR_DEVICELIST_ANNOUNCE(DR_DEVICELIST_ANNOUNCE *); +int APP_CC construct_DR_DEVICELIST_REMOVE(DR_DEVICELIST_REMOVE *); +int APP_CC construct_DR_DRIVE_CORE_DEVICE_IOREQUEST(DR_DRIVE_CORE_DEVICE_IOREQUEST *); +int APP_CC construct_DR_DRIVE_CREATE_REQ(DR_DRIVE_CREATE_REQ *); +int APP_CC construct_DR_DRIVE_CLOSE_REQ(DR_DRIVE_CLOSE_REQ *); +int APP_CC construct_DR_DRIVE_READ_REQ(DR_DRIVE_READ_REQ *); +int APP_CC construct_DR_DRIVE_WRITE_REQ(DR_DRIVE_WRITE_REQ *); +int APP_CC construct_DR_DRIVE_CONTROL_REQ(DR_DRIVE_CONTROL_REQ *); +int APP_CC construct_DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ(DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ *); +int APP_CC construct_DR_DRIVE_SET_VOLUME_INFORMATION_REQ(DR_DRIVE_SET_VOLUME_INFORMATION_REQ *); +int APP_CC construct_DR_DRIVE_QUERY_INFORMATION_REQ(DR_DRIVE_QUERY_INFORMATION_REQ *); +int APP_CC construct_DR_DRIVE_SET_INFORMATION_REQ(DR_DRIVE_SET_INFORMATION_REQ *); +int APP_CC construct_RDP_FILE_RENAME_INFORMATION(RDP_FILE_RENAME_INFORMATION *); +int APP_CC construct_DR_DRIVE_QUERY_DIRECTORY_REQ(DR_DRIVE_QUERY_DIRECTORY_REQ *); +int APP_CC construct_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ *); +int APP_CC construct_DR_DRIVE_LOCK_REQ(DR_DRIVE_LOCK_REQ *); +int APP_CC construct_DR_DRIVE_CORE_DEVICE_IOCOMPLETION(DR_DRIVE_CORE_DEVICE_IOCOMPLETION *); +int APP_CC construct_DR_DRIVE_CREATE_RSP(DR_DRIVE_CREATE_RSP *); +int APP_CC construct_DR_DRIVE_CLOSE_RSP(DR_DRIVE_CLOSE_RSP *); +int APP_CC construct_DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP(DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP *); +int APP_CC construct_DR_DRIVE_SET_VOLUME_INFORMATION_RSP(DR_DRIVE_SET_VOLUME_INFORMATION_RSP *); +int APP_CC construct_DR_DRIVE_QUERY_INFORMATION_RSP(DR_DRIVE_QUERY_INFORMATION_RSP *); +int APP_CC construct_DR_DRIVE_QUERY_DIRECTORY_RSP(DR_DRIVE_QUERY_DIRECTORY_RSP *); +int APP_CC construct_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP *); +int APP_CC construct_DR_DRIVE_LOCK_RSP(DR_DRIVE_LOCK_RSP *); +int APP_CC construct_DR_CORE_USER_LOGGEDON(DR_CORE_USER_LOGGEDON *); +int APP_CC construct_DR_DRIVE_SET_VOLUME_INFORMATION_RSP(DR_DRIVE_SET_VOLUME_INFORMATION_RSP *); +int APP_CC construct_DR_DRIVE_SET_INFORMATION_RSP(DR_DRIVE_SET_INFORMATION_RSP *); +int APP_CC construct_DYNVC_CAPS_VERSION1(DYNVC_CAPS_VERSION1 *); +int APP_CC construct_DYNVC_CAPS_VERSION2(DYNVC_CAPS_VERSION2 *); +int APP_CC construct_DYNVC_CAPS_RSP(DYNVC_CAPS_RSP *); +int APP_CC construct_DYNVC_CREATE_REQ(DYNVC_CREATE_REQ *); +int APP_CC construct_DYNVC_CREATE_RSP(DYNVC_CREATE_RSP *); +int APP_CC construct_DYNVC_DATA_FIRST(DYNVC_DATA_FIRST *); +int APP_CC construct_DYNVC_DATA(DYNVC_DATA *); +int APP_CC construct_DYNVC_CLOSE(DYNVC_CLOSE *); +int APP_CC construct_MSG_SNDIN_VERSION(MSG_SNDIN_VERSION *); +int APP_CC construct_MSG_SNDIN_FORMATS(MSG_SNDIN_FORMATS *); +int APP_CC construct_MSG_SNDIN_OPEN(MSG_SNDIN_OPEN *); +int APP_CC construct_WAVEFORMAT_EXTENSIBLE(WAVEFORMAT_EXTENSIBLE *); +int APP_CC construct_MSG_SNDIN_OPEN_REPLY(MSG_SNDIN_OPEN_REPLY *); +int APP_CC construct_MSG_SNDIN_DATA_INCOMING(MSG_SNDIN_DATA_INCOMING *); +int APP_CC construct_MSG_SNDIN_DATA(MSG_SNDIN_DATA *); +int APP_CC construct_MSG_SNDIN_FORMATCHANGE(MSG_SNDIN_FORMATCHANGE *); + +/* +int APP_CC send_( *); +int APP_CC get_( *); +*/ + + +/************************************************************************** + * + * senders / receivers (serializers) + */ + +int APP_CC get_FILE_BOTH_DIR_INFORMATION(FILE_BOTH_DIR_INFORMATION *, struct stream *); +int APP_CC send_FILE_BOTH_DIR_INFORMATION(FILE_BOTH_DIR_INFORMATION *, struct stream *); +int APP_CC send_RDPDR_HEADER(RDPDR_HEADER *, struct stream *); +int APP_CC get_RDPDR_HEADER(RDPDR_HEADER *, struct stream *); +int APP_CC send_DR_CORE_SERVER_ANNOUNCE_REQ(DR_CORE_SERVER_ANNOUNCE_REQ *, struct stream *); +int APP_CC get_DR_CORE_SERVER_ANNOUNCE_RSP(DR_CORE_SERVER_ANNOUNCE_RSP *, struct stream *); +int APP_CC get_DR_CORE_CLIENT_NAME_REQ(DR_CORE_CLIENT_NAME_REQ *, struct stream *); +int APP_CC send_DR_CORE_USER_LOGGEDON(DR_CORE_USER_LOGGEDON *, struct stream *); +int APP_CC get_DR_CORE_USER_LOGGEDON(DR_CORE_USER_LOGGEDON *, struct stream *); +int APP_CC send_CAPABILITY_HEADER(CAPABILITY_HEADER *, struct stream *); +int APP_CC get_CAPABILITY_HEADER(CAPABILITY_HEADER *, struct stream *); +int APP_CC send_DR_DEVICE_IOREQUEST(DR_DEVICE_IOREQUEST *, struct stream *); +int APP_CC get_DR_DEVICE_IOREQUEST(DR_DEVICE_IOREQUEST *, struct stream *); +int APP_CC send_DR_DEVICE_IOCOMPLETION(DR_DEVICE_IOCOMPLETION *, struct stream *); +int APP_CC get_DR_DEVICE_IOCOMPLETION(DR_DEVICE_IOCOMPLETION *, struct stream *); +int APP_CC send_DR_CREATE_REQ(DR_CREATE_REQ *, struct stream *); +int APP_CC get_DR_CREATE_REQ(DR_CREATE_REQ *, struct stream *); +int APP_CC send_DR_DRIVE_CREATE_REQ(DR_DRIVE_CREATE_REQ *, struct stream *); +int APP_CC get_DR_DRIVE_CREATE_REQ(DR_DRIVE_CREATE_REQ *, struct stream *); +int APP_CC send_DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ(DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ *, struct stream *); +int APP_CC get_DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ(DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ *, struct stream *); +int APP_CC send_DR_DRIVE_QUERY_DIRECTORY_REQ(DR_DRIVE_QUERY_DIRECTORY_REQ *, struct stream *); +int APP_CC get_DR_DRIVE_QUERY_DIRECTORY_REQ(DR_DRIVE_QUERY_DIRECTORY_REQ *, struct stream *); +int APP_CC send_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ *, struct stream *); +int APP_CC get_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ *, struct stream *); +int APP_CC send_DR_DRIVE_QUERY_DIRECTORY_RSP(DR_DRIVE_QUERY_DIRECTORY_RSP *, struct stream *); +int APP_CC get_DR_DRIVE_QUERY_DIRECTORY_RSP(DR_DRIVE_QUERY_DIRECTORY_RSP *, struct stream *); +int APP_CC get_CAPABILITY_SET(CAPABILITY_SET *, struct stream *); +int APP_CC get_DEVICE_ANNOUNCE(DEVICE_ANNOUNCE *, struct stream *); +int APP_CC get_DR_CLOSE_REQ(DR_CLOSE_REQ *, struct stream *); +int APP_CC get_DR_READ_REQ(DR_READ_REQ *, struct stream *); +int APP_CC get_DR_WRITE_REQ(DR_WRITE_REQ *, struct stream *); +int APP_CC get_DR_CONTROL_REQ(DR_CONTROL_REQ *, struct stream *); +int APP_CC get_DR_CREATE_RSP(DR_CREATE_RSP *, struct stream *); +int APP_CC get_DR_CLOSE_RSP(DR_CLOSE_RSP *, struct stream *); +int APP_CC get_DR_READ_RSP(DR_READ_RSP *, struct stream *); +int APP_CC get_DR_WRITE_RSP(DR_WRITE_RSP *, struct stream *); +int APP_CC get_DR_CONTROL_RSP(DR_CONTROL_RSP *, struct stream *); +int APP_CC get_RDP_LOCK_INFO(RDP_LOCK_INFO *, struct stream *); +int APP_CC get_DR_CORE_DEVICE_ANNOUNCE_RSP(DR_CORE_DEVICE_ANNOUNCE_RSP *, struct stream *); +int APP_CC get_DR_CORE_SERVER_ANNOUNCE_REQ(DR_CORE_SERVER_ANNOUNCE_REQ *, struct stream *); +int APP_CC get_DR_CORE_SERVER_CLIENTID_CONFIRM(DR_CORE_SERVER_CLIENTID_CONFIRM *, struct stream *); +int APP_CC get_DR_CORE_CAPABILITY_REQ(DR_CORE_CAPABILITY_REQ *, struct stream *); +int APP_CC get_GENERAL_CAPS_SET(GENERAL_CAPS_SET *, struct stream *); +int APP_CC get_PRINTER_CAPS_SET(PRINTER_CAPS_SET *, struct stream *); +int APP_CC get_PORT_CAPS_SET(PORT_CAPS_SET *, struct stream *); +int APP_CC get_DRIVE_CAPS_SET(DRIVE_CAPS_SET *, struct stream *); +int APP_CC get_SMARTCARD_CAPS_SET(SMARTCARD_CAPS_SET *, struct stream *); +int APP_CC get_DR_CORE_DEVICELIST_ANNOUNCE_REQ(DR_CORE_DEVICELIST_ANNOUNCE_REQ *, struct stream *); +int APP_CC get_DR_DEVICELIST_ANNOUNCE(DR_DEVICELIST_ANNOUNCE *, struct stream *); +int APP_CC get_DR_DEVICELIST_REMOVE(DR_DEVICELIST_REMOVE *, struct stream *); +int APP_CC get_DR_DRIVE_CORE_DEVICE_IOREQUEST(DR_DRIVE_CORE_DEVICE_IOREQUEST *, struct stream *); +int APP_CC get_DR_DRIVE_CLOSE_REQ(DR_DRIVE_CLOSE_REQ *, struct stream *); +int APP_CC get_DR_DRIVE_READ_REQ(DR_DRIVE_READ_REQ *, struct stream *); +int APP_CC get_DR_DRIVE_WRITE_REQ(DR_DRIVE_WRITE_REQ *, struct stream *); +int APP_CC get_DR_DRIVE_CONTROL_REQ(DR_DRIVE_CONTROL_REQ *, struct stream *); +int APP_CC get_DR_DRIVE_SET_VOLUME_INFORMATION_REQ(DR_DRIVE_SET_VOLUME_INFORMATION_REQ *, struct stream *); +int APP_CC get_DR_DRIVE_QUERY_INFORMATION_REQ(DR_DRIVE_QUERY_INFORMATION_REQ *, struct stream *); +int APP_CC get_DR_DRIVE_SET_INFORMATION_REQ(DR_DRIVE_SET_INFORMATION_REQ *, struct stream *); +int APP_CC get_RDP_FILE_RENAME_INFORMATION(RDP_FILE_RENAME_INFORMATION *, struct stream *); +int APP_CC get_DR_DRIVE_LOCK_REQ(DR_DRIVE_LOCK_REQ *, struct stream *); +int APP_CC get_DR_DRIVE_CORE_DEVICE_IOCOMPLETION(DR_DRIVE_CORE_DEVICE_IOCOMPLETION *, struct stream *); +int APP_CC get_DR_DRIVE_CREATE_RSP(DR_DRIVE_CREATE_RSP *, struct stream *); +int APP_CC get_DR_DRIVE_CLOSE_RSP(DR_DRIVE_CLOSE_RSP *, struct stream *); +int APP_CC get_DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP(DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP *, struct stream *); +int APP_CC get_DR_DRIVE_SET_VOLUME_INFORMATION_RSP(DR_DRIVE_SET_VOLUME_INFORMATION_RSP *, struct stream *); +int APP_CC get_DR_DRIVE_QUERY_INFORMATION_RSP(DR_DRIVE_QUERY_INFORMATION_RSP *, struct stream *); +int APP_CC get_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP *, struct stream *); +int APP_CC get_DR_DRIVE_LOCK_RSP(DR_DRIVE_LOCK_RSP *, struct stream *); +int APP_CC get_FILE_NAME_INFORMATION(FILE_NAME_INFORMATION *, struct stream *); +int APP_CC get_FILE_BASIC_INFORMATION(FILE_BASIC_INFORMATION *, struct stream *); +int APP_CC get_FILE_STANDARD_INFORMATION(FILE_STANDARD_INFORMATION *, struct stream *); +int APP_CC get_FILE_ALL_INFORMATION(FILE_ALL_INFORMATION *, struct stream *); +int APP_CC get_DR_DRIVE_SET_VOLUME_INFORMATION_RSP(DR_DRIVE_SET_VOLUME_INFORMATION_RSP *, struct stream *); +int APP_CC get_DR_DRIVE_SET_INFORMATION_RSP(DR_DRIVE_SET_INFORMATION_RSP *, struct stream *); +int APP_CC get_DYNVC_CAPS_VERSION1(DYNVC_CAPS_VERSION1 *, struct stream *); +int APP_CC get_DYNVC_CAPS_VERSION2(DYNVC_CAPS_VERSION2 *, struct stream *); +int APP_CC get_DYNVC_CAPS_RSP(DYNVC_CAPS_RSP *, struct stream *); +int APP_CC get_DYNVC_CREATE_REQ(DYNVC_CREATE_REQ *, struct stream *); +int APP_CC get_DYNVC_CREATE_RSP(DYNVC_CREATE_RSP *, struct stream *); +int APP_CC get_DYNVC_DATA_FIRST(DYNVC_DATA_FIRST *, struct stream *); +int APP_CC get_DYNVC_DATA(DYNVC_DATA *, struct stream *); +int APP_CC get_DYNVC_CLOSE(DYNVC_CLOSE *, struct stream *); +int APP_CC send_DYNVC_CAPS_VERSION1(DYNVC_CAPS_VERSION1 *, struct stream *); +int APP_CC send_DYNVC_CAPS_VERSION2(DYNVC_CAPS_VERSION2 *, struct stream *); +int APP_CC send_DYNVC_CREATE_REQ(DYNVC_CREATE_REQ *, struct stream *); +int APP_CC send_DYNVC_CREATE_RSP(DYNVC_CREATE_RSP *, struct stream *); +int APP_CC send_DYNVC_DATA_FIRST(DYNVC_DATA_FIRST *, struct stream *); +int APP_CC send_DYNVC_DATA(DYNVC_DATA *, struct stream *); +int APP_CC send_DYNVC_CLOSE(DYNVC_CLOSE *, struct stream *); +int APP_CC send_DYNVC_CAPS_RSP(DYNVC_CAPS_RSP *, struct stream *); +int APP_CC send_MSG_SNDIN_VERSION(MSG_SNDIN_VERSION *, struct stream *); +int APP_CC get_MSG_SNDIN_VERSION(MSG_SNDIN_VERSION *, struct stream *); +int APP_CC send_MSG_SNDIN_FORMATS(MSG_SNDIN_FORMATS *, struct stream *); +int APP_CC get_MSG_SNDIN_FORMATS(MSG_SNDIN_FORMATS *, struct stream *); +int APP_CC send_MSG_SNDIN_OPEN(MSG_SNDIN_OPEN *, struct stream *); +int APP_CC get_MSG_SNDIN_OPEN(MSG_SNDIN_OPEN *, struct stream *); +int APP_CC send_WAVEFORMAT_EXTENSIBLE(WAVEFORMAT_EXTENSIBLE *, struct stream *); +int APP_CC get_WAVEFORMAT_EXTENSIBLE(WAVEFORMAT_EXTENSIBLE *, struct stream *); +int APP_CC send_MSG_SNDIN_OPEN_REPLY(MSG_SNDIN_OPEN_REPLY *, struct stream *); +int APP_CC get_MSG_SNDIN_OPEN_REPLY(MSG_SNDIN_OPEN_REPLY *, struct stream *); +int APP_CC send_MSG_SNDIN_DATA_INCOMING(MSG_SNDIN_DATA_INCOMING *, struct stream *); +int APP_CC get_MSG_SNDIN_DATA_INCOMING(MSG_SNDIN_DATA_INCOMING *, struct stream *); +int APP_CC send_MSG_SNDIN_DATA(MSG_SNDIN_DATA *, struct stream *); +int APP_CC get_MSG_SNDIN_DATA(MSG_SNDIN_DATA *, struct stream *); +int APP_CC send_MSG_SNDIN_FORMATCHANGE(MSG_SNDIN_FORMATCHANGE *, struct stream *); +int APP_CC get_MSG_SNDIN_FORMATCHANGE(MSG_SNDIN_FORMATCHANGE *, struct stream *); + + +/************************************************************************** + * + * senders (serializers) + */ + +int APP_CC send_CAPABILITY_SET(CAPABILITY_SET *, struct stream *); +int APP_CC send_DEVICE_ANNOUNCE(DEVICE_ANNOUNCE *, struct stream *); +int APP_CC send_DR_CLOSE_REQ(DR_CLOSE_REQ *, struct stream *); +int APP_CC send_DR_READ_REQ(DR_READ_REQ *, struct stream *); +int APP_CC send_DR_WRITE_REQ(DR_WRITE_REQ *, struct stream *); +int APP_CC send_DR_CONTROL_REQ(DR_CONTROL_REQ *, struct stream *); +int APP_CC send_DR_CREATE_RSP(DR_CREATE_RSP *, struct stream *); +int APP_CC send_DR_CLOSE_RSP(DR_CLOSE_RSP *, struct stream *); +int APP_CC send_DR_READ_RSP(DR_READ_RSP *, struct stream *); +int APP_CC send_DR_WRITE_RSP(DR_WRITE_RSP *, struct stream *); +int APP_CC send_DR_CONTROL_RSP(DR_CONTROL_RSP *, struct stream *); +int APP_CC send_RDP_LOCK_INFO(RDP_LOCK_INFO *, struct stream *); +int APP_CC send_DR_CORE_DEVICE_ANNOUNCE_RSP(DR_CORE_DEVICE_ANNOUNCE_RSP *, struct stream *); +int APP_CC send_DR_CORE_SERVER_ANNOUNCE_RSP(DR_CORE_SERVER_ANNOUNCE_RSP *, struct stream *); +int APP_CC send_DR_CORE_CLIENT_NAME_REQ(DR_CORE_CLIENT_NAME_REQ *, struct stream *); +int APP_CC send_DR_CORE_SERVER_CLIENTID_CONFIRM(DR_CORE_SERVER_CLIENTID_CONFIRM *, struct stream *); +int APP_CC send_DR_CORE_CAPABILITY_REQ(DR_CORE_CAPABILITY_REQ *, struct stream *); +int APP_CC send_GENERAL_CAPS_SET(GENERAL_CAPS_SET *, struct stream *); +int APP_CC send_PRINTER_CAPS_SET(PRINTER_CAPS_SET *, struct stream *); +int APP_CC send_PORT_CAPS_SET(PORT_CAPS_SET *, struct stream *); +int APP_CC send_DRIVE_CAPS_SET(DRIVE_CAPS_SET *, struct stream *); +int APP_CC send_SMARTCARD_CAPS_SET(SMARTCARD_CAPS_SET *, struct stream *); +int APP_CC send_DR_CORE_DEVICELIST_ANNOUNCE_REQ(DR_CORE_DEVICELIST_ANNOUNCE_REQ *, struct stream *); +int APP_CC send_DR_DEVICELIST_ANNOUNCE(DR_DEVICELIST_ANNOUNCE *, struct stream *); +int APP_CC send_DR_DEVICELIST_REMOVE(DR_DEVICELIST_REMOVE *, struct stream *); +int APP_CC send_DR_DRIVE_CORE_DEVICE_IOREQUEST(DR_DRIVE_CORE_DEVICE_IOREQUEST *, struct stream *); +int APP_CC send_DR_DRIVE_CLOSE_REQ(DR_DRIVE_CLOSE_REQ *, struct stream *); +int APP_CC send_DR_DRIVE_READ_REQ(DR_DRIVE_READ_REQ *, struct stream *); +int APP_CC send_DR_DRIVE_WRITE_REQ(DR_DRIVE_WRITE_REQ *, struct stream *); +int APP_CC send_DR_DRIVE_CONTROL_REQ(DR_DRIVE_CONTROL_REQ *, struct stream *); +int APP_CC send_DR_DRIVE_SET_VOLUME_INFORMATION_REQ(DR_DRIVE_SET_VOLUME_INFORMATION_REQ *, struct stream *); +int APP_CC send_DR_DRIVE_QUERY_INFORMATION_REQ(DR_DRIVE_QUERY_INFORMATION_REQ *, struct stream *); +int APP_CC send_DR_DRIVE_SET_INFORMATION_REQ(DR_DRIVE_SET_INFORMATION_REQ *, struct stream *); +int APP_CC send_DR_DRIVE_SET_INFORMATION_REQ_rename(DR_DRIVE_SET_INFORMATION_REQ *, struct stream *); +int APP_CC send_RDP_FILE_RENAME_INFORMATION(RDP_FILE_RENAME_INFORMATION *, struct stream *); +int APP_CC send_DR_DRIVE_LOCK_REQ(DR_DRIVE_LOCK_REQ *, struct stream *); +int APP_CC send_DR_DRIVE_CORE_DEVICE_IOCOMPLETION(DR_DRIVE_CORE_DEVICE_IOCOMPLETION *, struct stream *); +int APP_CC send_DR_DRIVE_CREATE_RSP(DR_DRIVE_CREATE_RSP *, struct stream *); +int APP_CC send_DR_DRIVE_CLOSE_RSP(DR_DRIVE_CLOSE_RSP *, struct stream *); +int APP_CC send_DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP(DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP *, struct stream *); +int APP_CC send_DR_DRIVE_SET_VOLUME_INFORMATION_RSP(DR_DRIVE_SET_VOLUME_INFORMATION_RSP *, struct stream *); +int APP_CC send_DR_DRIVE_QUERY_INFORMATION_RSP(DR_DRIVE_QUERY_INFORMATION_RSP *, struct stream *); +int APP_CC send_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP *, struct stream *); +int APP_CC send_DR_DRIVE_LOCK_RSP(DR_DRIVE_LOCK_RSP *, struct stream *); +int APP_CC send_FILE_NAME_INFORMATION(FILE_NAME_INFORMATION *, struct stream *); +int APP_CC send_FILE_BASIC_INFORMATION(FILE_BASIC_INFORMATION *, struct stream *); +int APP_CC send_FILE_STANDARD_INFORMATION(FILE_STANDARD_INFORMATION *, struct stream *); +int APP_CC send_FILE_ALL_INFORMATION(FILE_ALL_INFORMATION *, struct stream *); +int APP_CC send_DR_DRIVE_SET_VOLUME_INFORMATION_RSP(DR_DRIVE_SET_VOLUME_INFORMATION_RSP *, struct stream *); +int APP_CC send_DR_DRIVE_SET_INFORMATION_RSP(DR_DRIVE_SET_INFORMATION_RSP *, struct stream *); + + + +/************************************************************************** + * + * destructors + */ + +void APP_CC destroy_RDPDR_HEADER(RDPDR_HEADER *); +void APP_CC destroy_CAPABILITY_HEADER(CAPABILITY_HEADER *); +void APP_CC destroy_CAPABILITY_SET(CAPABILITY_SET *); +void APP_CC destroy_DEVICE_ANNOUNCE(DEVICE_ANNOUNCE *); +void APP_CC destroy_DR_DEVICE_IOREQUEST(DR_DEVICE_IOREQUEST *); +void APP_CC destroy_DR_CREATE_REQ(DR_CREATE_REQ *); +void APP_CC destroy_DR_CLOSE_REQ(DR_CLOSE_REQ *); +void APP_CC destroy_DR_READ_REQ(DR_READ_REQ *); +void APP_CC destroy_DR_WRITE_REQ(DR_WRITE_REQ *); +void APP_CC destroy_DR_CONTROL_REQ(DR_CONTROL_REQ *); +void APP_CC destroy_DR_DEVICE_IOCOMPLETION(DR_DEVICE_IOCOMPLETION *); +void APP_CC destroy_DR_CREATE_RSP(DR_CREATE_RSP *); +void APP_CC destroy_DR_CLOSE_RSP(DR_CLOSE_RSP *); +void APP_CC destroy_DR_READ_RSP(DR_READ_RSP *); +void APP_CC destroy_DR_WRITE_RSP(DR_WRITE_RSP *); +void APP_CC destroy_DR_CONTROL_RSP(DR_CONTROL_RSP *); +void APP_CC destroy_RDP_LOCK_INFO(RDP_LOCK_INFO *); +void APP_CC destroy_DR_CORE_DEVICE_ANNOUNCE_RSP(DR_CORE_DEVICE_ANNOUNCE_RSP *); +void APP_CC destroy_DR_CORE_SERVER_ANNOUNCE_REQ(DR_CORE_SERVER_ANNOUNCE_REQ *); +void APP_CC destroy_DR_CORE_SERVER_ANNOUNCE_RSP(DR_CORE_SERVER_ANNOUNCE_RSP *); +void APP_CC destroy_DR_CORE_CLIENT_NAME_REQ(DR_CORE_CLIENT_NAME_REQ *); +void APP_CC destroy_DR_CORE_SERVER_CLIENTID_CONFIRM(DR_CORE_SERVER_CLIENTID_CONFIRM *); +void APP_CC destroy_DR_CORE_CAPABILITY_REQ(DR_CORE_CAPABILITY_REQ *); +void APP_CC destroy_GENERAL_CAPS_SET(GENERAL_CAPS_SET *); +void APP_CC destroy_PRINTER_CAPS_SET(PRINTER_CAPS_SET *); +void APP_CC destroy_PORT_CAPS_SET(PORT_CAPS_SET *); +void APP_CC destroy_DRIVE_CAPS_SET(DRIVE_CAPS_SET *); +void APP_CC destroy_SMARTCARD_CAPS_SET(SMARTCARD_CAPS_SET *); +void APP_CC destroy_DR_CORE_DEVICELIST_ANNOUNCE_REQ(DR_CORE_DEVICELIST_ANNOUNCE_REQ *); +void APP_CC destroy_DR_DEVICELIST_ANNOUNCE(DR_DEVICELIST_ANNOUNCE *); +void APP_CC destroy_DR_DEVICELIST_REMOVE(DR_DEVICELIST_REMOVE *); +void APP_CC destroy_DR_DRIVE_CORE_DEVICE_IOREQUEST(DR_DRIVE_CORE_DEVICE_IOREQUEST *); +void APP_CC destroy_DR_DRIVE_CREATE_REQ(DR_DRIVE_CREATE_REQ *); +void APP_CC destroy_DR_DRIVE_CLOSE_REQ(DR_DRIVE_CLOSE_REQ *); +void APP_CC destroy_DR_DRIVE_READ_REQ(DR_DRIVE_READ_REQ *); +void APP_CC destroy_DR_DRIVE_WRITE_REQ(DR_DRIVE_WRITE_REQ *); +void APP_CC destroy_DR_DRIVE_CONTROL_REQ(DR_DRIVE_CONTROL_REQ *); +void APP_CC destroy_DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ(DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ *); +void APP_CC destroy_DR_DRIVE_SET_VOLUME_INFORMATION_REQ(DR_DRIVE_SET_VOLUME_INFORMATION_REQ *); +void APP_CC destroy_DR_DRIVE_QUERY_INFORMATION_REQ(DR_DRIVE_QUERY_INFORMATION_REQ *); +void APP_CC destroy_DR_DRIVE_SET_INFORMATION_REQ(DR_DRIVE_SET_INFORMATION_REQ *); +void APP_CC destroy_RDP_FILE_RENAME_INFORMATION(RDP_FILE_RENAME_INFORMATION *); +void APP_CC destroy_DR_DRIVE_QUERY_DIRECTORY_REQ(DR_DRIVE_QUERY_DIRECTORY_REQ *); +void APP_CC destroy_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ *); +void APP_CC destroy_DR_DRIVE_LOCK_REQ(DR_DRIVE_LOCK_REQ *); +void APP_CC destroy_DR_DRIVE_CORE_DEVICE_IOCOMPLETION(DR_DRIVE_CORE_DEVICE_IOCOMPLETION *); +void APP_CC destroy_DR_DRIVE_CREATE_RSP(DR_DRIVE_CREATE_RSP *); +void APP_CC destroy_DR_DRIVE_CLOSE_RSP(DR_DRIVE_CLOSE_RSP *); +void APP_CC destroy_DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP(DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP *); +void APP_CC destroy_DR_DRIVE_SET_VOLUME_INFORMATION_RSP(DR_DRIVE_SET_VOLUME_INFORMATION_RSP *); +void APP_CC destroy_DR_DRIVE_QUERY_INFORMATION_RSP(DR_DRIVE_QUERY_INFORMATION_RSP *); +void APP_CC destroy_DR_DRIVE_QUERY_DIRECTORY_RSP(DR_DRIVE_QUERY_DIRECTORY_RSP *); +void APP_CC destroy_DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_RSP *); +void APP_CC destroy_DR_DRIVE_LOCK_RSP(DR_DRIVE_LOCK_RSP *); +void APP_CC destroy_DR_CORE_USER_LOGGEDON(DR_CORE_USER_LOGGEDON *); +void APP_CC destroy_DYNVC_CAPS_VERSION1(DYNVC_CAPS_VERSION1 *); +void APP_CC destroy_DYNVC_CAPS_VERSION2(DYNVC_CAPS_VERSION2 *); +void APP_CC destroy_DYNVC_CAPS_RSP(DYNVC_CAPS_RSP *); +void APP_CC destroy_DYNVC_CREATE_REQ(DYNVC_CREATE_REQ *); +void APP_CC destroy_DYNVC_CREATE_RSP(DYNVC_CREATE_RSP *); +void APP_CC destroy_DYNVC_DATA_FIRST(DYNVC_DATA_FIRST *); +void APP_CC destroy_DYNVC_DATA(DYNVC_DATA *); +void APP_CC destroy_DYNVC_CLOSE(DYNVC_CLOSE *); + + + +/************************************************************************** + * + * instantiators + */ + +void * APP_CC rdpdr_inst(const char *); + + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/rdpeai_defs.h posixrdp/posixxrdp.orig/common/rdpeai_defs.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/rdpeai_defs.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/rdpeai_defs.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,13 @@ +#if !defined(XRDP_RDPEAI_DEFS) +#define XRDP_RDPEAI_DEFS + + +typedef struct _SNDIN_PDU { + uint8_t MessageId; +} SNDIN_PDU; + +typedef struct _MSG_SNDIN_VERSION { +} MSG_SNDIN_VERSION; + + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/recording_defs.h posixrdp/posixxrdp.orig/common/recording_defs.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/recording_defs.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/recording_defs.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,129 @@ +#if !defined(__XRDP_SNDIN__) +#define __XRDP_SNDIN__ + + +#include +#include "devredir_defs.h" +#include "sound_defs.h" + + +/*****************************************************************************/ + +enum { + CMSG_SNDIN_VERSION = 0x01, +#define CMSG_SNDIN_VERSION CMSG_SNDIN_VERSION + CMSG_SNDIN_FORMATS = 0x02, +#define CMSG_SNDIN_FORMATS CMSG_SNDIN_FORMATS + CMSG_SNDIN_OPEN = 0x03, +#define CMSG_SNDIN_OPEN CMSG_SNDIN_OPEN + CMSG_SNDIN_OPEN_REPLY = 0x04, +#define CMSG_SNDIN_OPEN_REPLY CMSG_SNDIN_OPEN_REPLY + CMSG_SNDIN_DATA_INCOMING = 0x05, +#define CMSG_SNDIN_DATA_INCOMING CMSG_SNDIN_DATA_INCOMING + CMSG_SNDIN_DATA = 0x06, +#define CMSG_SNDIN_DATA CMSG_SNDIN_DATA + CMSG_SNDIN_FORMATCHANGE = 0x07 +#define CMSG_SNDIN_FORMATCHANGE CMSG_SNDIN_FORMATCHANGE +}; + +#define SNDIN_VERSION 0x00000001 + +typedef struct _AUDIO_FORMAT_REC { + WORD wFormatTag; + WORD nChannels; + DWORD nSamplesPerSec; + DWORD nAvgBytesPerSec; + WORD nBlockAlign; + WORD wBitsPerSample; + WORD cbSize; /* cbSize = the number of bytes contained by data[] */ + BYTE data[0]; +} AUDIO_FORMAT_REC, WAVEFORMATEX_REC; + +typedef struct _SNDIN_PDU { + uint8_t MessageId; +} SNDIN_PDU; + +typedef struct _MSG_SNDIN_VERSION { + SNDIN_PDU Header; + DWORD Version; +} MSG_SNDIN_VERSION; + +typedef struct _MSG_SNDIN_FORMATS { + SNDIN_PDU Header; + DWORD NumFormats; + DWORD cbSizeFormatsPacket; + AUDIO_FORMAT_REC SoundFormats[0]; +/* BYTE ExtraData[0]; */ +} MSG_SNDIN_FORMATS; + +typedef struct _MSG_SNDIN_OPEN { + SNDIN_PDU Header; + DWORD FramesPerPacket; + DWORD initialFormat; + WORD wFormatTag; + WORD nChannels; + DWORD nSamplesPerSec; + DWORD nAvgBytesPerSec; + WORD nBlockAlign; + WORD wBitsPerSample; + WORD cbSize; + BYTE ExtraFormatData[0]; + /* + * if wFormatTag == WAVE_FORMAT_EXTENSIBLE, + * then ExtraFormatData must be a structure + * of type WAVEFORMAT_EXTENSIBLE. + */ +} MSG_SNDIN_OPEN; + +#define WAVE_FORMAT_EXTENSIBLE 0xFFFE + +typedef struct _WAVEFORMAT_EXTENSIBLE { + WORD wValidBitsPerSample; + DWORD dwChannelMask; + GUID SubFormat; /* this field MUST be set to KSDATAFORMAT_SUBTYPE_PCM ({00000001-0000-0010-8000-00aa00389b71}) */ + #define KSDATAFORMAT_SUBTYPE_PCM { 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } } + /* #define KSDATAFORMAT_SUBTYPE_PCM 00000001-0000-0010-8000-00aa00389b71 */ + #define SPEAKER_FRONT_LEFT 0x00000001 + #define SPEAKER_FRONT_RIGHT 0x00000002 + #define SPEAKER_FRONT_CENTER 0x00000004 + #define SPEAKER_LOW_FREQUENCY 0x00000008 + #define SPEAKER_BACK_LEFT 0x00000010 + #define SPEAKER_BACK_RIGHT 0x00000020 + #define SPEAKER_FRONT_LEFT_OF_CENTER 0x00000040 + #define SPEAKER_FRONT_RIGHT_OF_CENTER 0x00000080 + #define SPEAKER_BACK_CENTER 0x00000100 + #define SPEAKER_SIDE_LEFT 0x00000200 + #define SPEAKER_SIDE_RIGHT 0x00000400 + #define SPEAKER_TOP_CENTER 0x00000800 + #define SPEAKER_TOP_FRONT_LEFT 0x00001000 + #define SPEAKER_TOP_FRONT_CENTER 0x00002000 + #define SPEAKER_TOP_FRONT_RIGHT 0x00004000 + #define SPEAKER_TOP_BACK_LEFT 0x00008000 + #define SPEAKER_TOP_BACK_CENTER 0x00010000 + #define SPEAKER_TOP_BACK_RIGHT 0x00020000 +} WAVEFORMAT_EXTENSIBLE; + +typedef DWORD HRESULT; + +typedef struct _MSG_SNDIN_OPEN_REPLY { + SNDIN_PDU Header; + HRESULT Result; +} MSG_SNDIN_OPEN_REPLY; + +typedef struct _MSG_SNDIN_DATA_INCOMING { + SNDIN_PDU Header; +} MSG_SNDIN_DATA_INCOMING; + +typedef struct _MSG_SNDIN_DATA { + SNDIN_PDU Header; + size_t len; + BYTE Data[0]; +} MSG_SNDIN_DATA; + +typedef struct _MSG_SNDIN_FORMATCHANGE { + SNDIN_PDU Header; + DWORD NewFormat; +} MSG_SNDIN_FORMATCHANGE; + + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/ringbuffer.c posixrdp/posixxrdp.orig/common/ringbuffer.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/ringbuffer.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/ringbuffer.c 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,309 @@ +/* + Copyright (C) 2000 Paul Davis + Copyright (C) 2003 Rohan Drape + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Adapted (i.e., copied verbatim) from JACK Audio's ringbuffer.c + + ISO/POSIX C version of Paul Davis's lock free ringbuffer C++ code. + This is safe for the case of one read thread and one write thread. +*/ + +#include +#include +#include +#include "ringbuffer.h" + +/* Create a new ringbuffer to hold at least `sz' bytes of data. The + actual buffer size is rounded up to the next power of two. */ + +xrdp_ringbuffer_t * +xrdp_ringbuffer_create (size_t sz) +{ + int power_of_two; + xrdp_ringbuffer_t *rb; + + rb = malloc (sizeof (xrdp_ringbuffer_t)); + + for (power_of_two = 1; 1 << power_of_two < sz; power_of_two++); + + rb->size = 1 << power_of_two; + rb->size_mask = rb->size; + rb->size_mask -= 1; + rb->write_ptr = 0; + rb->read_ptr = 0; + rb->buf = malloc (rb->size); + rb->mlocked = 0; + + return rb; +} + +/* Free all data associated with the ringbuffer `rb'. */ + +void +xrdp_ringbuffer_free (xrdp_ringbuffer_t * rb) +{ + if (rb->mlocked) { + munlock (rb->buf, rb->size); + } + free (rb->buf); +} + +/* Lock the data block of `rb' using the system call 'mlock'. */ + +int +xrdp_ringbuffer_mlock (xrdp_ringbuffer_t * rb) +{ + if (mlock (rb->buf, rb->size)) { + return -1; + } + rb->mlocked = 1; + return 0; +} + +/* Reset the read and write pointers to zero. This is not thread + safe. */ + +void +xrdp_ringbuffer_reset (xrdp_ringbuffer_t * rb) +{ + rb->read_ptr = 0; + rb->write_ptr = 0; +} + +/* Return the number of bytes available for reading. This is the + number of bytes in front of the read pointer and behind the write + pointer. */ + +size_t +xrdp_ringbuffer_read_space (xrdp_ringbuffer_t * rb) +{ + size_t w, r; + + w = rb->write_ptr; + r = rb->read_ptr; + + if (w > r) { + return w - r; + } else { + return (w - r + rb->size) & rb->size_mask; + } +} + +/* Return the number of bytes available for writing. This is the + number of bytes in front of the write pointer and behind the read + pointer. */ + +size_t +xrdp_ringbuffer_write_space (xrdp_ringbuffer_t * rb) +{ + size_t w, r; + + w = rb->write_ptr; + r = rb->read_ptr; + + if (w > r) { + return ((r - w + rb->size) & rb->size_mask) - 1; + } else if (w < r) { + return (r - w) - 1; + } else { + return rb->size - 1; + } +} + +/* The copying data reader. Copy at most `cnt' bytes from `rb' to + `dest'. Returns the actual number of bytes copied. */ + +size_t +xrdp_ringbuffer_read (xrdp_ringbuffer_t * rb, char *dest, size_t cnt) +{ + size_t free_cnt; + size_t cnt2; + size_t to_read; + size_t n1, n2; + + if ((free_cnt = xrdp_ringbuffer_read_space (rb)) == 0) { + return 0; + } + + to_read = cnt > free_cnt ? free_cnt : cnt; + + cnt2 = rb->read_ptr + to_read; + + if (cnt2 > rb->size) { + n1 = rb->size - rb->read_ptr; + n2 = cnt2 & rb->size_mask; + } else { + n1 = to_read; + n2 = 0; + } + + memcpy (dest, &(rb->buf[rb->read_ptr]), n1); + rb->read_ptr += n1; + rb->read_ptr &= rb->size_mask; + + if (n2) { + memcpy (dest + n1, &(rb->buf[rb->read_ptr]), n2); + rb->read_ptr += n2; + rb->read_ptr &= rb->size_mask; + } + + return to_read; +} + +/* The copying data writer. Copy at most `cnt' bytes to `rb' from + `src'. Returns the actual number of bytes copied. */ + +size_t +xrdp_ringbuffer_write (xrdp_ringbuffer_t * rb, char *src, size_t cnt) +{ + size_t free_cnt; + size_t cnt2; + size_t to_write; + size_t n1, n2; + + if ((free_cnt = xrdp_ringbuffer_write_space (rb)) == 0) { + return 0; + } + + to_write = cnt > free_cnt ? free_cnt : cnt; + + cnt2 = rb->write_ptr + to_write; + + if (cnt2 > rb->size) { + n1 = rb->size - rb->write_ptr; + n2 = cnt2 & rb->size_mask; + } else { + n1 = to_write; + n2 = 0; + } + + memcpy (&(rb->buf[rb->write_ptr]), src, n1); + rb->write_ptr += n1; + rb->write_ptr &= rb->size_mask; + + if (n2) { + memcpy (&(rb->buf[rb->write_ptr]), src + n1, n2); + rb->write_ptr += n2; + rb->write_ptr &= rb->size_mask; + } + + return to_write; +} + +/* Advance the read pointer `cnt' places. */ + +void +xrdp_ringbuffer_read_advance (xrdp_ringbuffer_t * rb, size_t cnt) +{ + rb->read_ptr += cnt; + rb->read_ptr &= rb->size_mask; +} + +/* Advance the write pointer `cnt' places. */ + +void +xrdp_ringbuffer_write_advance (xrdp_ringbuffer_t * rb, size_t cnt) +{ + rb->write_ptr += cnt; + rb->write_ptr &= rb->size_mask; +} + +/* The non-copying data reader. `vec' is an array of two places. Set + the values at `vec' to hold the current readable data at `rb'. If + the readable data is in one segment the second segment has zero + length. */ + +void +xrdp_ringbuffer_get_read_vector (xrdp_ringbuffer_t * rb, + xrdp_ringbuffer_data_t * vec) +{ + size_t free_cnt; + size_t cnt2; + size_t w, r; + + w = rb->write_ptr; + r = rb->read_ptr; + + if (w > r) { + free_cnt = w - r; + } else { + free_cnt = (w - r + rb->size) & rb->size_mask; + } + + cnt2 = r + free_cnt; + + if (cnt2 > rb->size) { + + /* Two part vector: the rest of the buffer after the current write + ptr, plus some from the start of the buffer. */ + + vec[0].buf = &(rb->buf[r]); + vec[0].len = rb->size - r; + vec[1].buf = rb->buf; + vec[1].len = cnt2 & rb->size_mask; + + } else { + + /* Single part vector: just the rest of the buffer */ + + vec[0].buf = &(rb->buf[r]); + vec[0].len = free_cnt; + vec[1].len = 0; + } +} + +/* The non-copying data writer. `vec' is an array of two places. Set + the values at `vec' to hold the current writeable data at `rb'. If + the writeable data is in one segment the second segment has zero + length. */ + +void +xrdp_ringbuffer_get_write_vector (xrdp_ringbuffer_t * rb, + xrdp_ringbuffer_data_t * vec) +{ + size_t free_cnt; + size_t cnt2; + size_t w, r; + + w = rb->write_ptr; + r = rb->read_ptr; + + if (w > r) { + free_cnt = ((r - w + rb->size) & rb->size_mask) - 1; + } else if (w < r) { + free_cnt = (r - w) - 1; + } else { + free_cnt = rb->size - 1; + } + + cnt2 = w + free_cnt; + + if (cnt2 > rb->size) { + + /* Two part vector: the rest of the buffer after the current write + ptr, plus some from the start of the buffer. */ + + vec[0].buf = &(rb->buf[w]); + vec[0].len = rb->size - w; + vec[1].buf = rb->buf; + vec[1].len = cnt2 & rb->size_mask; + } else { + vec[0].buf = &(rb->buf[w]); + vec[0].len = free_cnt; + vec[1].len = 0; + } +} diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/ringbuffer.h posixrdp/posixxrdp.orig/common/ringbuffer.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/ringbuffer.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/ringbuffer.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,218 @@ +/* + Copyright (C) 2000 Paul Davis + Copyright (C) 2003 Rohan Drape + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + $Id: ringbuffer.h,v 1.4 2003/12/21 02:40:46 joq Exp $ +*/ + +#ifndef _XRDP_RINGBUFFER_H +#define _XRDP_RINGBUFFER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** @file ringbuffer.h + * + * A set of library functions to make lock-free ringbuffers available + * to JACK clients. The `capture_client.c' (in the example_clients + * directory) is a fully functioning user of this API. + * + * The key attribute of a ringbuffer is that it can be safely accessed + * by two threads simultaneously -- one reading from the buffer and + * the other writing to it -- without using any synchronization or + * mutual exclusion primitives. For this to work correctly, there can + * only be a single reader and a single writer thread. Their + * identities cannot be interchanged. + */ + +typedef struct +{ + char *buf; + size_t len; +} +xrdp_ringbuffer_data_t ; + +typedef struct +{ + char *buf; + volatile size_t write_ptr; + volatile size_t read_ptr; + size_t size; + size_t size_mask; + int mlocked; +} +xrdp_ringbuffer_t ; + +/** + * Allocates a ringbuffer data structure of a specified size. The + * caller must arrange for a call to xrdp_ringbuffer_free() to release + * the memory associated with the ringbuffer. + * + * @param sz the ringbuffer size in bytes. + * + * @return a pointer to a new xrdp_ringbuffer_t, if successful; NULL + * otherwise. + */ +xrdp_ringbuffer_t *xrdp_ringbuffer_create(size_t sz); + +/** + * Frees the ringbuffer data structure allocated by an earlier call to + * xrdp_ringbuffer_create(). + * + * @param rb a pointer to the ringbuffer structure. + */ +void xrdp_ringbuffer_free(xrdp_ringbuffer_t *rb); + +/** + * Fill a data structure with a description of the current readable + * data held in the ringbuffer. This description is returned in a two + * element array of xrdp_ringbuffer_data_t. Two elements are needed + * because the data to be read may be split across the end of the + * ringbuffer. + * + * The first element will always contain a valid @a len field, which + * may be zero or greater. If the @a len field is non-zero, then data + * can be read in a contiguous fashion using the address given in the + * corresponding @a buf field. + * + * If the second element has a non-zero @a len field, then a second + * contiguous stretch of data can be read from the address given in + * its corresponding @a buf field. + * + * @param rb a pointer to the ringbuffer structure. + * @param vec a pointer to a 2 element array of xrdp_ringbuffer_data_t. + * + */ +void xrdp_ringbuffer_get_read_vector(xrdp_ringbuffer_t *rb, + xrdp_ringbuffer_data_t *vec); + +/** + * Fill a data structure with a description of the current writable + * space in the ringbuffer. The description is returned in a two + * element array of xrdp_ringbuffer_data_t. Two elements are needed + * because the space available for writing may be split across the end + * of the ringbuffer. + * + * The first element will always contain a valid @a len field, which + * may be zero or greater. If the @a len field is non-zero, then data + * can be written in a contiguous fashion using the address given in + * the corresponding @a buf field. + * + * If the second element has a non-zero @a len field, then a second + * contiguous stretch of data can be written to the address given in + * the corresponding @a buf field. + * + * @param rb a pointer to the ringbuffer structure. + * @param vec a pointer to a 2 element array of xrdp_ringbuffer_data_t. + */ +void xrdp_ringbuffer_get_write_vector(xrdp_ringbuffer_t *rb, + xrdp_ringbuffer_data_t *vec); + +/** + * Read data from the ringbuffer. + * + * @param rb a pointer to the ringbuffer structure. + * @param dest a pointer to a buffer where data read from the + * ringbuffer will go. + * @param cnt the number of bytes to read. + * + * @return the number of bytes read, which may range from 0 to cnt. + */ +size_t xrdp_ringbuffer_read(xrdp_ringbuffer_t *rb, char *dest, size_t cnt); + +/** + * Advance the read pointer. + * + * After data have been read from the ringbuffer using the pointers + * returned by xrdp_ringbuffer_get_read_vector(), use this function to + * advance the buffer pointers, making that space available for future + * write operations. + * + * @param rb a pointer to the ringbuffer structure. + * @param cnt the number of bytes read. + */ +void xrdp_ringbuffer_read_advance(xrdp_ringbuffer_t *rb, size_t cnt); + +/** + * Return the number of bytes available for reading. + * + * @param rb a pointer to the ringbuffer structure. + * + * @return the number of bytes available to read. + */ +size_t xrdp_ringbuffer_read_space(xrdp_ringbuffer_t *rb); + +/** + * Lock a ringbuffer data block into memory. + * + * Uses the mlock() system call. This is not a realtime operation. + * + * @param rb a pointer to the ringbuffer structure. + */ +int xrdp_ringbuffer_mlock(xrdp_ringbuffer_t *rb); + +/** + * Reset the read and write pointers, making an empty buffer. + * + * This is not thread safe. + * + * @param rb a pointer to the ringbuffer structure. + */ +void xrdp_ringbuffer_reset(xrdp_ringbuffer_t *rb); + +/** + * Write data into the ringbuffer. + * + * @param rb a pointer to the ringbuffer structure. + * @param src a pointer to the data to be written to the ringbuffer. + * @param cnt the number of bytes to write. + * + * @return the number of bytes write, which may range from 0 to cnt + */ +size_t xrdp_ringbuffer_write(xrdp_ringbuffer_t *rb, char *src, size_t cnt); + +/** + * Advance the write pointer. + * + * After data have been written the ringbuffer using the pointers + * returned by xrdp_ringbuffer_get_write_vector(), use this function + * to advance the buffer pointer, making the data available for future + * read operations. + * + * @param rb a pointer to the ringbuffer structure. + * @param cnt the number of bytes written. + */ +void xrdp_ringbuffer_write_advance(xrdp_ringbuffer_t *rb, size_t cnt); + +/** + * Return the number of bytes available for writing. + * + * @param rb a pointer to the ringbuffer structure. + * + * @return the amount of free space (in bytes) available for writing. + */ +size_t xrdp_ringbuffer_write_space(xrdp_ringbuffer_t *rb); + + +#ifdef __cplusplus +} +#endif + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/sound_defs.h posixrdp/posixxrdp.orig/common/sound_defs.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/sound_defs.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/sound_defs.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,214 @@ +#ifndef _RDPSND_DEFS_ +#define _RDPSND_DEFS_ + +#include +#include + +/* MS PDU definitions */ +#define SNDC_CLOSE 0x01 +#define SNDC_WAVE 0x02 +#define SNDC_SETVOLUME 0x03 +#define SNDC_SETPITCH 0x04 +#define SNDC_WAVECONFIRM 0x05 +#define SNDC_TRAINING 0x06 +#define SNDC_FORMATS 0x07 +#define SNDC_CRYPTKEY 0x08 +#define SNDC_WAVEENCRYPT 0x09 +#define SNDC_UDPWAVE 0x0A +#define SNDC_UDPWAVELAST 0x0B +#define SNDC_QUALITYMODE 0x0C + +/* MS Wave Format definitions */ +#define WAVE_FORMAT_UNKNOWN 0x0000 +#define WAVE_FORMAT_PCM 0x0001 +#define WAVE_FORMAT_ADPCM 0x0002 +#define WAVE_FORMAT_ALAW 0x0006 +#define WAVE_FORMAT_MULAW 0x0007 +#define WAVE_FORMAT_ULAW 0x0007 +#define WAVE_FORMAT_IMA_ADPCM 0x0011 +#define WAVE_FORMAT_DSPGROUP_TRUESPEECH 0x0022 +#define WAVE_FORMAT_GSM610 0x0031 +#define WAVE_FORMAT_MSG723 0x0042 +#define WAVE_FORMAT_MPEGLAYER3 0x0055 +#define WAVE_FORMAT_VOXWARE_AC8 0x0070 +#define WAVE_FORMAT_VOXWARE_AC10 0x0071 +#define WAVE_FORMAT_VOXWARE_AC16 0x0072 +#define WAVE_FORMAT_VOXWARE_AC20 0x0073 +/* + Windows XP (0x02): +*/ +#define XRDP_DEFAULT_WAVE_FORMAT 0x0001 +#define ADPCM_WFX_EXTRA_BYTES 0x0020 /* = 32 */ +#define MPEGLAYER3_WFX_EXTRA_BYTES 0x000C /* = 12 */ +#define MPEGLAYER3_FLAG_PADDING_ON 0x00000001 +#define MPEGLAYER3_FLAG_PADDING_OFF 0x00000002 +#define MPEGLAYER3_ID_MPEG 0x00000001 +#define MPEGLAYER3_NBLOCKSIZE 313 +#define MPEGLAYER3_NFRAMESPERBLOCK 1 +#define MPEGLAYER3_NCODECDELAY 1393 + +#define TSSNDCAPS_ALIVE 0x00000001 +#define TSSNDCAPS_VOLUME 0x00000002 +#define TSSNDCAPS_PITCH 0x00000004 + +typedef uint8_t BYTE; +typedef uint16_t WORD; +typedef uint32_t DWORD; +typedef uint64_t QWORD; + +void * APP_CC sound_inst(const char *); + +#ifndef _SNDPROLOG_ +#define _SNDPROLOG_ +typedef struct _SNDPROLOG { + BYTE msgType; + BYTE bPad; + WORD BodySize; +} SNDPROLOG; +#endif + +typedef struct _SNDCLOSE { + SNDPROLOG Header; + void (*__constructor)(); + void (*__destructor)(void *); +} SNDCLOSE; + +#ifndef _AUDIO_FORMAT_ +#define _AUDIO_FORMAT_ +typedef struct _AUDIO_FORMAT { + WORD wFormatTag; + WORD nChannels; + DWORD nSamplesPerSec; + DWORD nAvgBytesPerSec; + WORD nBlockAlign; + WORD wBitsPerSample; + WORD cbSize; /* cbSize = the number of bytes contained by data[] */ + void (*__constructor)(); + void (*__destructor)(void *); + BYTE data[0]; /* data[cbSize] */ +} AUDIO_FORMAT, WAVEFORMATEX; +#endif + +#ifndef _MP3MWF_ +#define _MP3MWF_ +typedef struct _MPEGLAYER3WAVEFORMAT { + /* WAVEFORMATEX wfx; */ + WORD wID; + DWORD fdwFlags; + WORD nBlockSize; + WORD nFramesPerBlock; + WORD nCodecDelay; +} MPEGLAYER3WAVEFORMAT; +#endif + +#ifndef GUID_TYPE +#define GUID_TYPE +typedef struct _GUID { + DWORD /* unsigned long */ f1; + WORD /* unsigned short */ f2; + WORD /* unsigned short */ f3; + BYTE /* unsigned char */ f4[8]; +} GUID; +#endif /* GUID_TYPE */ + +#ifndef _WAVEFORMATEXTENSIBLE_ +#define _WAVEFORMATEXTENSIBLE_ +typedef struct _WAVEFORMATEXTENSIBLE { + WAVEFORMATEX Format; + union { + WORD wValidBitsPerSample; /* bits of precision */ + WORD wSamplesPerBlock; /* valid if wBitsPerSample==0 */ + WORD wReserved; /* If neither applies, set to zero. */ + } Samples; + DWORD dwChannelMask; /* which channels are */ + /* present in stream */ + GUID SubFormat; +} WAVEFORMATEXTENSIBLE; +#endif /* _WAVEFORMATEXTENSIBLE_ */ + +typedef struct _SNDWAV { + DWORD bPad; + BYTE *Data; + void (*__constructor)(); + void (*__destructor)(void *); +} SNDWAV; + +typedef struct _SNDWAVINFO { + SNDPROLOG Header; + WORD wTimeStamp; + WORD wFormatNo; + BYTE cBlockNo; + BYTE bPad[3]; + DWORD Data; + unsigned int alen; + SNDWAV *appendix; + void (*__constructor)(); + void (*__destructor)(void *); +} SNDWAVINFO; + +typedef struct _SNDWAV_CONFIRM { + SNDPROLOG Header; + WORD wTimeStamp; + BYTE cConfirmedBlockNo; + BYTE bPad; + void (*__constructor)(); + void (*__destructor)(void *); +} SNDWAV_CONFIRM; + +typedef struct _SNDTRAINING { + SNDPROLOG Header; + WORD wTimeStamp; + WORD wPackSize; + BYTE *data; + void (*__constructor)(); + void (*__destructor)(void *); +} SNDTRAINING; + +typedef struct _SNDTRAININGCONFIRM { + SNDPROLOG Header; + WORD wTimeStamp; + WORD wPackSize; + void (*__constructor)(); + void (*__destructor)(void *); +} SNDTRAININGCONFIRM; + +typedef struct _AUDIO_VERSION_AND_FORMATS { + SNDPROLOG Header; + DWORD dwFlags; + DWORD dwVolume; + DWORD dwPitch; + WORD wDGramPort; + WORD wNumberOfFormats; + BYTE cLastBlockConfirmed; + WORD wVersion; + BYTE bPad; + void (*__constructor)(); + void (*__destructor)(void *); + tc_t lock; + AUDIO_FORMAT ** sndFormats; +} CLIENT_AUDIO_VERSION_AND_FORMATS, SERVER_AUDIO_VERSION_AND_FORMATS; + +typedef struct _QUALITY_MODE { + SNDPROLOG Header; + WORD wQualityMode; + WORD Reserved; + void (*__constructor)(); + void (*__destructor)(void *); +} QUALITY_MODE; + + +#if !defined(SOUND_NEW) +#define SOUND_NEW(c) (c *)sound_inst(#c) +#endif +#if !defined(SOUND_FREE) +#define SOUND_FREE(itm) { \ + if (itm != NULL) { \ + if ( (*itm->__destructor) != NULL ) { \ + (*itm->__destructor)((void *)itm); \ + } \ + itm = NULL; \ + } \ +} +#endif + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/stream_list.h posixrdp/posixxrdp.orig/common/stream_list.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/stream_list.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/stream_list.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,140 @@ +#if !defined(__XRDP_STREAM_LIST__) +#define __XRDP_STREAM_LIST__ + + +#include +#include + +#include "arch.h" +#include "defines.h" +#include "os_calls.h" +#include "parse.h" +#if defined(__XRDP_STREAM_LIST_THREADS__) +#include "thread_calls.h" +#include "thread_macros.h" +#endif + +struct stream_list; + +typedef struct stream_list { + struct stream * s; + struct stream_list * next; + struct stream_list * prev; +#if defined(__XRDP_STREAM_LIST_THREADS__) + tc_t lock; +#endif +} stream_list_t, * stream_list_p; + + + +#define SQ_CREATE() (stream_list_t *)g_malloc(sizeof(stream_list_t), 1) +#if defined(__XRDP_STREAM_LIST_THREADS__) +#define SQ_INIT(x) { \ + if (x != NULL) { \ + tc_t l_tattr; \ + tc_p p_tattr = (tc_p)(&l_tattr); \ + g_memset((void *)(&l_tattr),0,sizeof(tc_t)); \ + TC_MUTATTR_INIT((tc_p)p_tattr); \ + /* TC_MUTEX_INIT((tc_p)(&(x->lock)), (tc_p)p_tattr); */ \ + } \ +} +#else +#define SQ_INIT(x) 0 +#endif +#define DECLARE_SQ(inx) \ + stream_list_t * inx = (stream_list_t *)NULL; \ + { \ + inx = SQ_CREATE(); \ + if (inx != NULL) { \ + SQ_INIT(inx); \ + } \ + } +#define SQ_ENQ(t,x) { \ + if (t == NULL) { \ + t = x; \ + if (t != NULL) { \ + t->prev = NULL; \ + t->next = NULL; \ + } \ + } \ + else { \ + stream_list_t * tlmp = (stream_list_t *)NULL; \ + tlmp = t; \ + while (tlmp != NULL && tlmp->next != NULL) { \ + tlmp = tlmp->next; \ + } \ + tlmp->next = x; \ + if (x != NULL) { \ + x->prev = tlmp; \ + x->next = NULL; \ + } \ + } \ +} +#define SQ_DEQ(t,x) { \ + if (x != NULL) { \ + (*(x)) = t; \ + if ((*(x)) != NULL) { \ + (*(x))->prev = NULL; \ + (*(x))->next = NULL; \ + } \ + } \ + if (t != NULL) { \ + t = t->next; \ + if (t != NULL) { \ + t->prev = NULL; \ + } \ + } \ +} +#define SQ_FIND(t, x, y, z) { \ + if (t == NULL) { \ + z = NULL; \ + } \ + else { \ + int tdone = 0; \ + stream_list_t * tlmp = (stream_list_t *)NULL; \ + z = tlmp; \ + tlmp = t; \ + if (tlmp != NULL && tlmp->device_id == x && tlmp->opid == y) { \ + z = tlmp; \ + tdone = 1; \ + } \ + while (tlmp != NULL && tdone < 1) { \ + if (tlmp->device_id == x && tlmp->opid == y) { \ + z = tlmp; \ + tdone = 1; \ + } \ + else { \ + tlmp = tlmp->next; \ + } \ + } \ + } \ +} +#define SQ_CUT(t, x) { \ + if (x != NULL) { \ + if (x->prev == NULL) { \ + t = t->next; \ + if (t != NULL) { \ + t->prev = NULL; \ + } \ + } \ + else if (x->prev != NULL) { \ + x->prev->next = x->next; \ + if (x->next != NULL) { \ + x->next->prev = x->prev; \ + } \ + } \ + } \ +} +#define SQ_COUNT(t, x) { \ + stream_list_t * tmp = t; \ + x = 0; \ + while (tmp != NULL) { \ + x++; \ + tmp = tmp->next; \ + } \ +} + + + + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/stringlist.c posixrdp/posixxrdp.orig/common/stringlist.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/stringlist.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/stringlist.c 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,127 @@ +#include +#include +#include "stringlist.h" +#include "os_calls.h" +#include "dbg.h" + +strlist * strlist_init(void) { + strlist * ret = (strlist *)NULL; + return ret; +} + +strlist * strlist_empty(void) { + strlist * ret = (strlist *)NULL; + ret = (strlist *)g_malloc(sizeof(strlist),1); + g_memset(ret,0,sizeof(strlist)); + ret->str = (char *)NULL; + ret->next = (void *)NULL; + return ret; +} + +strlist * strlist_append(strlist ** self, const char * text) { + int n = 0; + strlist * itm = (strlist *)NULL; + strlist * final = (strlist *)NULL; + strlist * ret = (strlist *)NULL; + ret = *self; + final = *self; + itm = strlist_empty(); + itm->str = g_strdup(text); + itm->next = (void *)NULL; + if (final == NULL) { + ret = itm; + } + else { + while (final->next != NULL) { + final = (strlist *)final->next; + n++; + } + final->next = (void *)itm; + ret = *self; + } + return ret; +} + +strlist * strlist_remove(strlist ** self, strlist * itm) { + unsigned int found = 0; + strlist * prev = (strlist *)NULL; + strlist * cur = (strlist *)NULL; + strlist * ret = (strlist *)NULL; + cur = *self; + ret = *self; + if (cur != NULL) { + while (cur->next != NULL && found == 0) { + if (cur == itm) { + found = 1; + } + prev = cur; + cur = (strlist *)cur->next; + } + if (found == 1) { + prev->next = cur->next; + g_free(cur->str); + cur->str = (char *)NULL; + g_free(cur); + } + } + return ret; +} + +strlist * strlist_find(strlist * self, const char * text) { + unsigned int found = 0; + strlist * ret = (strlist *)NULL; + if (text != NULL) { + ret = self; + } + while (ret != NULL && found == 0) { + found = g_strcmp(text,ret->str); + ret = (strlist *)ret->next; + } + return ret; +} + +int strlist_count(strlist * self) { + int ret = 0; + while (self != NULL) { + ret++; + self = (strlist *)self->next; + } + return ret; +} + +strlist * strlist_free(strlist * self) { + strlist * itm = (strlist *)NULL; + strlist * prev = (strlist *)NULL; + itm = self; + while (itm != NULL) { + prev = itm; + itm = (strlist *)itm->next; + g_free(prev->str); + prev->next = (void *)NULL; + g_free(prev); + } + return NULL; +} + +char ** strlist_to_array(strlist * self, int * count) { + char ** ret = (char **)NULL; + int idx = 0; + *count = strlist_count(self); + ret = (char **)g_malloc((*count + 1),1); + while (self != NULL) { + ret[idx] = g_strdup(self->str); + self = (strlist *)self->next; + idx++; + } + return ret; +} + +strlist * array_to_strlist(const char ** arr, int count) { + strlist * ret = (strlist *)NULL; + int idx = 0; + ret = strlist_init(); + for (idx = 0;idx < count;idx++) { + ret = strlist_append(&ret, arr[idx]); + } + return ret; +} diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/stringlist.h posixrdp/posixxrdp.orig/common/stringlist.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/stringlist.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/stringlist.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,22 @@ +#ifndef __strlist__ +#define __strlist__ + +#include +#include + +typedef struct { + char * str; + void * next; +} strlist; + +strlist * strlist_init(void); +strlist * strlist_empty(void); +strlist * strlist_append(strlist **, const char *); +strlist * strlist_remove(strlist **, strlist *); +strlist * strlist_free(strlist *); +strlist * strlist_find(strlist *, const char *); +int strlist_count(strlist *); +char ** strlist_to_array(strlist *, int *); +strlist * array_to_strlist(const char **, int); + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/thread_calls.c posixrdp/posixxrdp.orig/common/thread_calls.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/thread_calls.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/thread_calls.c 2010-11-08 09:56:43.000000000 +0100 @@ -28,20 +28,23 @@ #else #include #include +#include +#include #endif #include "arch.h" #include "thread_calls.h" #include "os_calls.h" + /*****************************************************************************/ /* returns error */ #if defined(_WIN32) -int APP_CC +tc_thread_t APP_CC tc_thread_create(unsigned long (__stdcall * start_routine)(void*), void* arg) { - DWORD thread_id; - HANDLE thread; - int rv; + int rv = 0; + DWORD thread_id = 0; + HANDLE thread = (HANDLE)0; /* CreateThread returns handle or zero on error */ thread = CreateThread(0, 0, start_routine, arg, 0, &thread_id); @@ -50,34 +53,114 @@ return rv; } #else -int APP_CC -tc_thread_create(void* (* start_routine)(void*), void* arg) +tc_thread_t APP_CC +tc_thread_create(void * (* start_routine)(void *), void * arg) { - pthread_t thread; - int rv; + int rv = 0; + pthread_t thread = (pthread_t)0; + + g_memset(&thread, 0x00, sizeof(pthread_t)); /* pthread_create returns error */ rv = pthread_create(&thread, 0, start_routine, arg); - pthread_detach(thread); + if (!rv) { + rv = pthread_detach(thread); + } + return rv; +} +#endif + +/*****************************************************************************/ +int APP_CC +tc_thread_init_full(tc_thread_t * itid, const tc_threadattr_t * tattrs, void * (* start_routine)(void *), void * targs) { + int rv = 0; + pthread_t * tid = (pthread_t *)NULL; + tid = (pthread_t *)itid; + if (itid == NULL || start_routine == NULL) { + rv = -1; + } + else { +#if defined(_WIN32) + DWORD thread_id; + *tid = CreateThread(0, 0, start_routine, targs, 0, &thread_id); +#else + rv = pthread_create(tid,tattrs,start_routine,targs); + } +#endif return rv; } + +/*****************************************************************************/ +int APP_CC +tc_thread_init(tc_thread_t * itid, void * (* start_routine)(void *), void * targs) { + int rv = 0; + pthread_t * tid = (pthread_t *)NULL; + tid = (pthread_t *)itid; + if (itid == NULL || start_routine == NULL) { + rv = -1; + } + else { +#if defined(_WIN32) + DWORD thread_id; + *tid = CreateThread(0, 0, start_routine, arg, 0, &thread_id); +#else + pthread_attr_t lattr; + g_memset(&lattr,0,sizeof(pthread_attr_t)); + pthread_attr_init(&lattr); + pthread_attr_setdetachstate(&lattr, PTHREAD_CREATE_JOINABLE); + rv = pthread_create(tid,&lattr,start_routine,targs); #endif + } + return rv; +} + +/*****************************************************************************/ +int APP_CC +tc_thread_join(tc_thread_t itid, void ** inarg) { + int rv = 0; +#if defined(_WIN32) + HANDLE tid; + tid = (HANDLE)itid; + WaitForSingleObject(tid, INFINITE); +#else + pthread_t tid; + g_memset(&tid, 0, sizeof(pthread_t)); + tid = (pthread_t)itid; + rv = pthread_join(tid, inarg); +#endif + return rv; +} + +/*****************************************************************************/ +void APP_CC +tc_thread_exit(void * arg) { +#if defined(_WIN32) +#else + pthread_exit(arg); +#endif +} + +/*****************************************************************************/ +int APP_CC +tc_thread_signal(tc_thread_t arg, int sig) { + return pthread_kill(arg, sig); +} /*****************************************************************************/ -tbus APP_CC +tc_thread_t APP_CC tc_get_threadid(void) { #if defined(_WIN32) - return (tbus)GetCurrentThreadId(); + return (tc_thread_t)GetCurrentThreadId(); #else - return (tbus)pthread_self(); + return (tc_thread_t)pthread_self(); #endif } /*****************************************************************************/ /* returns boolean */ int APP_CC -tc_threadid_equal(tbus tid1, tbus tid2) +tc_threadid_equal(tc_thread_t tid1, tc_thread_t tid2) { #if defined(_WIN32) return tid1 == tid2; @@ -87,82 +170,303 @@ } /*****************************************************************************/ -tbus APP_CC +int APP_CC +tc_mutex_init(tc_p ival, tc_p args) { + int rv = 0; +#if defined(_WIN32) +#else + pthread_mutex_t * lmutex = (pthread_mutex_t *)NULL; + pthread_mutexattr_t *lattr = (pthread_mutexattr_t *)NULL; + + if (ival == NULL) { + rv = -1; + } + else { + lmutex = (pthread_mutex_t *)(ival); + lattr = (pthread_mutexattr_t *)(args); + } + if (lattr == NULL) { + pthread_mutexattr_t tattr; + g_memset(&tattr,0,sizeof(pthread_mutexattr_t)); + lattr = &tattr; + pthread_mutexattr_init(lattr); + pthread_mutexattr_settype(lattr, TC_MUTEX_ERRORCHECK); + } + if (lmutex != NULL) { + rv = pthread_mutex_init(lmutex, lattr); + } +#endif + return rv; +} + +/*****************************************************************************/ +tc_p APP_CC tc_mutex_create(void) { #if defined(_WIN32) - return (tbus)CreateMutex(0, 0, 0); + return (tc_p)CreateMutex(0, 0, 0); #else - pthread_mutex_t* lmutex; + tc_p rv = (tc_p)NULL; + //pthread_mutex_t * lmutex = (pthread_mutex_t *)NULL; + tc_p lmutex = (tc_p)NULL; - lmutex = (pthread_mutex_t*)g_malloc(sizeof(pthread_mutex_t), 0); - pthread_mutex_init(lmutex, 0); - return (tbus)lmutex; + lmutex = (tc_p)g_malloc(sizeof(pthread_mutex_t), 1); + if (lmutex != NULL) { + if (!tc_mutex_init(lmutex, NULL)) { + rv = (tc_p)lmutex; + } + } + return rv; #endif } /*****************************************************************************/ -void APP_CC -tc_mutex_delete(tbus mutex) +int APP_CC +tc_mutex_delete(tc_p mutex) +{ + int rv = 0; +#if defined(_WIN32) + rv = CloseHandle((HANDLE)mutex); +#else + if (mutex != NULL) { + pthread_mutex_t * lmutex = (pthread_mutex_t *)NULL; + lmutex = (pthread_mutex_t *)(mutex); + rv = pthread_mutex_destroy(lmutex); + } +#endif + return rv; +} + +/*****************************************************************************/ +int APP_CC +tc_mutex_deinit(tc_p mutex) { + int rv = 0; #if defined(_WIN32) - CloseHandle((HANDLE)mutex); + rv = CloseHandle((HANDLE)mutex); #else - pthread_mutex_t* lmutex; + if (mutex != NULL) { + pthread_mutex_t * lmutex = (pthread_mutex_t *)NULL; + lmutex = (pthread_mutex_t *)(mutex); + rv = pthread_mutex_destroy(lmutex); + } +#endif + return rv; +} - lmutex = (pthread_mutex_t*)mutex; - pthread_mutex_destroy(lmutex); - g_free(lmutex); +/*****************************************************************************/ +int APP_CC +tc_mutex_lock(tc_p mutex) +{ + int rv = 0; +#if defined(_WIN32) + WaitForSingleObject((HANDLE)mutex, INFINITE); +#else + if (mutex == NULL) { + rv = -1; + } + else { + rv = pthread_mutex_lock((pthread_mutex_t *)(mutex)); + } #endif + return rv; } /*****************************************************************************/ int APP_CC -tc_mutex_lock(tbus mutex) +tc_mutex_trylock(tc_p mutex) { + int rv = 0; #if defined(_WIN32) WaitForSingleObject((HANDLE)mutex, INFINITE); - return 0; #else - pthread_mutex_lock((pthread_mutex_t*)mutex); - return 0; + if (mutex != NULL) { + rv = pthread_mutex_trylock((pthread_mutex_t *)mutex); + } #endif + return rv; } /*****************************************************************************/ int APP_CC -tc_mutex_unlock(tbus mutex) +tc_mutex_unlock(tc_p mutex) { + int rv = 0; #if defined(_WIN32) ReleaseMutex((HANDLE)mutex); - return 0; #else - pthread_mutex_unlock((pthread_mutex_t*)mutex); - return 0; + if (mutex != NULL) { + rv = pthread_mutex_unlock((pthread_mutex_t *)mutex); + } +#endif + return rv; +} + +/*****************************************************************************/ +int APP_CC +tc_mutex_timedlock(tc_p mutex, const struct timespec * itime) { + int rv = 0; +#if defined(_WIN32) +#else + pthread_mutex_t * p_mut = (pthread_mutex_t *)mutex; + + if (mutex == NULL || itime == NULL) { + rv = -1; + } + else { + rv = pthread_mutex_timedlock(p_mut, itime); + } #endif + return rv; +} + +/*****************************************************************************/ +int APP_CC +tc_mutattr_init(tc_p attr) { + int rv = 0; + pthread_mutexattr_t * tattr = (pthread_mutexattr_t *)NULL; + if (attr == NULL) { + rv = -1; + } + else { + tattr = (pthread_mutexattr_t *)attr; + rv = pthread_mutexattr_init(tattr); + } + return rv; +} + +/*****************************************************************************/ +int APP_CC +tc_mutattr_settype(tc_p attr, int itype) { + int rv = 0; + pthread_mutexattr_t * tattr = (pthread_mutexattr_t *)NULL; + if (attr == NULL) { + rv = -1; + } + else { + tattr = (pthread_mutexattr_t *)attr; + rv = pthread_mutexattr_settype(tattr, itype); + } + return rv; } /*****************************************************************************/ -tbus APP_CC +int APP_CC +tc_mutattr_gettype(tc_p attr) { + int rv = 0; + pthread_mutexattr_t * tattr = (pthread_mutexattr_t *)NULL; + if (attr == NULL) { + rv = -1; + } + else { + tattr = (pthread_mutexattr_t *)attr; + //rv = pthread_mutexattr_gettype(tattr); + } + return rv; +} + +/*****************************************************************************/ +int APP_CC +tc_mutattr_setpshared(tc_p attr, int ipshared) { + int rv = 0; + pthread_mutexattr_t * tattr = (pthread_mutexattr_t *)NULL; + if (attr == NULL) { + rv = -1; + } + else { + tattr = (pthread_mutexattr_t *)attr; + rv = pthread_mutexattr_setpshared(tattr, ipshared); + } + return rv; +} + +/*****************************************************************************/ +int APP_CC +tc_mutattr_getpshared(const tc_p attr, int * ipshared) { + int rv = 0; + if (attr == NULL) { + rv = -1; + } + else { + int lv = 0; + const pthread_mutexattr_t * tattr = (const pthread_mutexattr_t *)attr; + rv = pthread_mutexattr_getpshared(tattr, &lv); + if (ipshared == NULL) { + rv = lv; + } + else { + *ipshared = lv; + } + } + return rv; +} + +/*****************************************************************************/ +int APP_CC +tc_mutattr_setprotocol(tc_p attr, int iproto) { + int rv = 0; + pthread_mutexattr_t * tattr = (pthread_mutexattr_t *)NULL; + if (attr == NULL) { + rv = -1; + } + else { + tattr = (pthread_mutexattr_t *)attr; + rv = pthread_mutexattr_setprotocol(tattr, iproto); + } + return rv; +} + +/*****************************************************************************/ +int APP_CC +tc_mutattr_getprotocol(tc_p attr) { + int rv = 0; + pthread_mutexattr_t * tattr = (pthread_mutexattr_t *)NULL; + if (attr == NULL) { + rv = -1; + } + else { + tattr = (pthread_mutexattr_t *)attr; + //rv = pthread_mutexattr_getprotocol(tattr); + } + return rv; +} + +/*****************************************************************************/ +int APP_CC +tc_mutattr_destroy(tc_p attr) { + int rv = 0; + pthread_mutexattr_t * tattr = (pthread_mutexattr_t *)NULL; + if (attr == NULL) { + rv = -1; + } + else { + tattr = (pthread_mutexattr_t *)attr; + rv = pthread_mutexattr_destroy(tattr); + } + return rv; +} + +/*****************************************************************************/ +tc_p APP_CC tc_sem_create(int init_count) { #if defined(_WIN32) HANDLE sem; sem = CreateSemaphore(0, init_count, init_count + 10, 0); - return (tbus)sem; + return (tc_p)sem; #else - sem_t* sem; + sem_t * sem = (sem_t *)NULL; - sem = g_malloc(sizeof(sem_t), 0); + sem = (sem_t *)g_malloc(sizeof(sem_t), 0); sem_init(sem, 0, init_count); - return (tbus)sem; + return (tc_p)sem; #endif } /*****************************************************************************/ void APP_CC -tc_sem_delete(tbus sem) +tc_sem_delete(tc_p sem) { #if defined(_WIN32) CloseHandle((HANDLE)sem); @@ -176,8 +480,22 @@ } /*****************************************************************************/ +void APP_CC +tc_sem_deinit(tc_p sem) +{ +#if defined(_WIN32) + CloseHandle((HANDLE)sem); +#else + sem_t* lsem; + + lsem = (sem_t*)sem; + sem_destroy(lsem); +#endif +} + +/*****************************************************************************/ int APP_CC -tc_sem_dec(tbus sem) +tc_sem_dec(tc_p sem) { #if defined(_WIN32) WaitForSingleObject((HANDLE)sem, INFINITE); @@ -190,7 +508,7 @@ /*****************************************************************************/ int APP_CC -tc_sem_inc(tbus sem) +tc_sem_inc(tc_p sem) { #if defined(_WIN32) ReleaseSemaphore((HANDLE)sem, 1, 0); @@ -200,3 +518,573 @@ return 0; #endif } + +/*****************************************************************************/ +int APP_CC +tc_cond_create(tc_p icv, const tc_p ica) { + int rv = 0; + pthread_cond_t * cv = (pthread_cond_t *)NULL; + cv = (pthread_cond_t *)icv; +#if defined(_WIN32) + cv->waiters_count_ = 0; + cv->was_broadcast_ = 0; + cv->sema_ = CreatedSemaphore (NULL, // no security + 0, // initially 0 + 0x7fffffff, // max count + NULL); // unnamed + InitializeCriticalSection (&cv->waiters_count_lock_); + cv->waiters_done_ = CreateEvent (NULL, // no security + FALSE, // auto-reset + FALSE, // non-signaled initially + NULL); // unnamed +#else + if (cv == NULL) { + rv = -1; + } + else { + const pthread_condattr_t * ca = (pthread_condattr_t *)ica; + rv = pthread_cond_init(cv, ca); + } +#endif + return rv; +} + +/*****************************************************************************/ +int APP_CC tc_cond_wait (tc_p icv, tc_p iem) { + int rv = 0; + pthread_cond_t * cv = (pthread_cond_t *)NULL; + pthread_mutex_t * external_mutex = (pthread_mutex_t *)NULL; + cv = (pthread_cond_t *)icv; + external_mutex = (pthread_mutex_t *)iem; +#if defined(_WIN32) + // Avoid race conditions. + EnterCriticalSection (&cv->waiters_count_lock_); + cv->waiters_count_++; + LeaveCriticalSection (&cv->waiters_count_lock_); + + // This call atomically releases the mutex and waits on the + // semaphore until or + // are called by another thread. + SignalObjectAndWait (*external_mutex, cv->sema_, INFINITE, FALSE); + + // Reacquire lock to avoid race conditions. + EnterCriticalSection (&cv->waiters_count_lock_); + + // We're no longer waiting... + cv->waiters_count_--; + + // Check to see if we're the last waiter after . + int last_waiter = cv->was_broadcast_ && cv->waiters_count_ == 0; + + LeaveCriticalSection (&cv->waiters_count_lock_); + + // If we're the last waiter thread during this particular broadcast + // then let all the other threads proceed. + if (last_waiter) + // This call atomically signals the event and waits until + // it can acquire the . This is required to ensure fairness. + SignalObjectAndWait (cv->waiters_done_, *external_mutex, INFINITE, FALSE); + else + // Always regain the external mutex since that's the guarantee we + // give to our callers. + WaitForSingleObject (*external_mutex); +#else + if (cv == NULL || external_mutex == NULL) { + rv = -1; + } + else { + rv = pthread_cond_wait(cv, external_mutex); + } +#endif + return rv; +} + +/*****************************************************************************/ +int APP_CC tc_cond_timedwait (tc_p icv, tc_p iem, tc_future_t tos) { + int rv = 0; + pthread_cond_t * cv = (pthread_cond_t *)NULL; + pthread_mutex_t * external_mutex = (pthread_mutex_t *)NULL; + cv = (pthread_cond_t *)icv; + external_mutex = (pthread_mutex_t *)iem; +#if defined(_WIN32) + // Avoid race conditions. + EnterCriticalSection (&cv->waiters_count_lock_); + cv->waiters_count_++; + LeaveCriticalSection (&cv->waiters_count_lock_); + + // This call atomically releases the mutex and waits on the + // semaphore until or + // are called by another thread. + SignalObjectAndWait (*external_mutex, cv->sema_, INFINITE, FALSE); + + // Reacquire lock to avoid race conditions. + EnterCriticalSection (&cv->waiters_count_lock_); + + // We're no longer waiting... + cv->waiters_count_--; + + // Check to see if we're the last waiter after . + int last_waiter = cv->was_broadcast_ && cv->waiters_count_ == 0; + + LeaveCriticalSection (&cv->waiters_count_lock_); + + // If we're the last waiter thread during this particular broadcast + // then let all the other threads proceed. + if (last_waiter) + // This call atomically signals the event and waits until + // it can acquire the . This is required to ensure fairness. + SignalObjectAndWait (cv->waiters_done_, *external_mutex, INFINITE, FALSE); + else + // Always regain the external mutex since that's the guarantee we + // give to our callers. + WaitForSingleObject (*external_mutex); +#else + if (tos < 0 || cv == NULL || external_mutex == NULL) { + rv = -1; + } + else { + struct timespec lts; + struct timespec * ts = (struct timespec *)(<s); + g_memset(ts,0,sizeof(struct timespec)); + ts->tv_sec = (long int)tos; + rv = pthread_cond_timedwait(cv, external_mutex, ts); + } +#endif + return rv; +} + +/*****************************************************************************/ +int APP_CC tc_cond_signal (tc_p icv) { + int rv = 0; + pthread_cond_t * cv = (pthread_cond_t *)NULL; + cv = (pthread_cond_t *)icv; +#if defined(_WIN32) + EnterCriticalSection (&cv->waiters_count_lock_); + int have_waiters = cv->waiters_count_ > 0; + LeaveCriticalSection (&cv->waiters_count_lock_); + + // If there aren't any waiters, then this is a no-op. + if (have_waiters) + ReleaseSemaphore (cv->sema_, 1, 0); +#else + if (cv == NULL) { + rv = -1; + } + else { + rv = pthread_cond_signal(cv); + } +#endif + return rv; +} + +/*****************************************************************************/ +int APP_CC tc_cond_broadcast (tc_p icv) { + int rv = 0; + pthread_cond_t * cv = (pthread_cond_t *)NULL; + cv = (pthread_cond_t *)icv; +#if defined(_WIN32) + int have_waiters = 0; + // This is needed to ensure that and are + // consistent relative to each other. + EnterCriticalSection (&cv->waiters_count_lock_); + + if (cv->waiters_count_ > 0) { + // We are broadcasting, even if there is just one waiter... + // Record that we are broadcasting, which helps optimize + // for the non-broadcast case. + cv->was_broadcast_ = 1; + have_waiters = 1; + } + + if (have_waiters) { + // Wake up all the waiters atomically. + ReleaseSemaphore (cv->sema_, cv->waiters_count_, 0); + + LeaveCriticalSection (&cv->waiters_count_lock_); + + // Wait for all the awakened threads to acquire the counting + // semaphore. + WaitForSingleObject (cv->waiters_done_, INFINITE); + // This assignment is okay, even without the held + // because no other waiter threads can wake up to access it. + cv->was_broadcast_ = 0; + } + else { + LeaveCriticalSection (&cv->waiters_count_lock_); + } +#else + if (cv == NULL) { + rv = -1; + } + else { + rv = pthread_cond_broadcast(cv); + } +#endif + return rv; +} + +/*****************************************************************************/ +int APP_CC tc_cond_delete(tc_p cv) { + int rv = 0; + if (cv == 0) { + rv = -1; + } + else { +#if defined(_WIN32) + CloseHandle(((pthread_cond_t *)cv)->sema_); + CloseHandle(((pthread_cond_t *)cv)->waiters_done_); +#else + pthread_cond_t * lcv = (pthread_cond_t *)NULL; + lcv = (pthread_cond_t *)cv; + rv = pthread_cond_destroy(lcv); +#endif + } + return rv; +} + +/*****************************************************************************/ +int APP_CC tc_cond_deinit(tc_p cv) { + int rv = 0; + if (cv == 0) { + rv = -1; + } + else { +#if defined(_WIN32) + CloseHandle(((pthread_cond_t *)cv)->sema_); + CloseHandle(((pthread_cond_t *)cv)->waiters_done_); +#else + pthread_cond_t * lcv = (pthread_cond_t *)NULL; + lcv = (pthread_cond_t *)cv; + rv = pthread_cond_destroy(lcv); +#endif + } + return rv; +} + +/*****************************************************************************/ +int APP_CC tc_condattr_init(tc_p cv) { + int rv = 0; + if (cv == NULL) { + rv = -1; + } + else { + pthread_condattr_t * tcv = (pthread_condattr_t *)cv; + rv = pthread_condattr_init(tcv); + } + return rv; +} + +/*****************************************************************************/ +int APP_CC tc_condattr_deinit(tc_p cv) { + int rv = 0; + if (cv == NULL) { + rv = -1; + } + else { + pthread_condattr_t * tcv = (pthread_condattr_t *)cv; + rv = pthread_condattr_destroy(tcv); + } + return rv; +} + +int APP_CC tc_condattr_getpshared(const tc_p cv, int * ipsh) { + int rv = 0; + if (cv == NULL) { + rv = -1; + } + else { + const pthread_condattr_t * tcv = (const pthread_condattr_t *)cv; + rv = pthread_condattr_getpshared(tcv, ipsh); + } + return rv; +} + +int APP_CC tc_condattr_setpshared(tc_p cv, int ipsh) { + int rv = 0; + if (cv == NULL) { + rv = -1; + } + else { + pthread_condattr_t * tcv = (pthread_condattr_t *)cv; + rv = pthread_condattr_setpshared(tcv, ipsh); + } + return rv; +} + +/*****************************************************************************/ +int APP_CC +tc_threadattr_init(tc_p attr) { + if (attr == NULL) { + return -1; + } + else { + return pthread_attr_init((pthread_attr_t *)attr); + } +} + +/*****************************************************************************/ +int APP_CC +tc_threadattr_getdetachstate(const tc_p attr, int * st) { + if (attr == NULL || st == NULL) { + return -1; + } + else { + return pthread_attr_getdetachstate((const pthread_attr_t *)attr, st); + } +} + +/*****************************************************************************/ +int APP_CC +tc_threadattr_setdetachstate(tc_p attr, int st) { + if (attr == NULL) { + return -1; + } + else { + return pthread_attr_setdetachstate((pthread_attr_t *)attr, st); + } +} + +/*****************************************************************************/ +int APP_CC +tc_threadattr_getscope(const tc_p attr, int * sc) { + if (attr == NULL) { + return -1; + } + else { + return pthread_attr_getscope((const pthread_attr_t *)attr, sc); + } +} + +/*****************************************************************************/ +int APP_CC +tc_threadattr_setscope(tc_p attr, int sc) { + if (attr == NULL) { + return -1; + } + else { + return pthread_attr_setscope((pthread_attr_t *)attr, sc); + } +} + +/*****************************************************************************/ +int APP_CC tc_threadattr_setstacksize(tc_p ta, size_t len) { + int rv = 0; + rv = pthread_attr_setstacksize((pthread_attr_t *)ta, len); + return rv; +} + +/*****************************************************************************/ +int APP_CC tc_threadattr_getstacksize(tc_p ta, size_t * plen) { + int rv = 0; + rv = pthread_attr_getstacksize((pthread_attr_t *)ta, plen); + return rv; +} + +#if defined(__USE_XOPEN2K) + +/*****************************************************************************/ +int APP_CC +tc_barrattr_init(tc_p arg) { + int rv = 0; + if (arg == NULL) { + rv = -1; + } + else { + rv = pthread_barrierattr_init((pthread_barrierattr_t *)arg); + } + return rv; +} + +/*****************************************************************************/ +int APP_CC +tc_barrattr_setpshared(tc_p arg, int val) { + int rv = 0; + if (arg == NULL) { + rv = -1; + } + else { + rv = pthread_barrierattr_setpshared((pthread_barrierattr_t *)arg, val); + } + return rv; +} + +/*****************************************************************************/ +int APP_CC +tc_barrier_init(tc_p arg, int num) { + int rv = 0; + if (arg == NULL || num < 1) { + rv = -1; + } + else { + pthread_barrierattr_t attr; + pthread_barrierattr_t * pattr = &attr; + pthread_barrier_t * a = (pthread_barrier_t *)arg; + if (pattr != NULL) { + g_memset(pattr,0,sizeof(pthread_barrierattr_t)); + pthread_barrierattr_init(pattr); + rv = pthread_barrier_init(a, pattr, num); + } + else { + rv = -1; + } + } + return rv; +} + +/*****************************************************************************/ +int APP_CC +tc_barrier_init_full(tc_p arg, tc_p attr, int num) { + int rv = 0; + if (arg == NULL || num < 1) { + rv = -1; + } + else { + pthread_barrier_t * a = (pthread_barrier_t *)arg; + pthread_barrierattr_t * b = (pthread_barrierattr_t *)attr; + rv = pthread_barrier_init(a, b, num); + } + return rv; +} + +/*****************************************************************************/ +int APP_CC +tc_barrier_deinit(tc_p arg) { + int rv = 0; + if (arg == NULL) { + rv = -1; + } + else { + rv = pthread_barrier_destroy(&(arg->barrier)); + } + return rv; +} + +/*****************************************************************************/ +int APP_CC +tc_barrier_wait(tc_p arg) { + int rv = 0; + if (arg == NULL) { + rv = -1; + } + else { + rv = pthread_barrier_wait(&(arg->barrier)); + } + return rv; +} + +/*****************************************************************************/ +int APP_CC tc_spin_init(tc_p sl) { + int rv = 0; + pthread_spinlock_t * psl = (pthread_spinlock_t *)NULL; + + if (sl == 0) { + rv = -1; + } + else { + psl = (pthread_spinlock_t *)sl; +// rv = pthread_spin_init(psl, PTHREAD_PROCESS_SHARED); + rv = pthread_spin_init(psl, PTHREAD_PROCESS_PRIVATE); + } + + return rv; +} + +/*****************************************************************************/ +int APP_CC tc_spin_destroy(tc_p sl) { + int rv = 0; + pthread_spinlock_t * psl = (pthread_spinlock_t *)NULL; + + if (sl == 0) { + rv = -1; + } + else { + psl = (pthread_spinlock_t *)sl; + rv = pthread_spin_destroy(psl); + } + + return rv; +} + +/*****************************************************************************/ +int APP_CC tc_spin_deinit(tc_p sl) { + int rv = 0; + pthread_spinlock_t * psl = (pthread_spinlock_t *)NULL; + + if (sl == 0) { + rv = -1; + } + else { + psl = (pthread_spinlock_t *)sl; + rv = pthread_spin_destroy(psl); + } + + return rv; +} + +/*****************************************************************************/ +int APP_CC tc_spin_lock(tc_p sl) { + int rv = 0; + pthread_spinlock_t * psl = (pthread_spinlock_t *)NULL; + + if (sl == 0) { + rv = -1; + } + else { + psl = (pthread_spinlock_t *)sl; + rv = pthread_spin_lock(psl); + } + + return rv; +} + +/*****************************************************************************/ +int APP_CC tc_spin_unlock(tc_p sl) { + int rv = 0; + pthread_spinlock_t * psl = (pthread_spinlock_t *)NULL; + + if (sl == 0) { + rv = -1; + } + else { + psl = (pthread_spinlock_t *)sl; + rv = pthread_spin_unlock(psl); + } + + return rv; +} + +/*****************************************************************************/ +int APP_CC tc_spin_trylock(tc_p sl) { + int rv = 0; + pthread_spinlock_t * psl = (pthread_spinlock_t *)NULL; + + if (sl == 0) { + rv = -1; + } + else { + psl = (pthread_spinlock_t *)sl; + rv = pthread_spin_trylock(psl); + } + + return rv; +} + +void * t_malloc(void * mut, size_t len, unsigned char z) { + void * rv = (void *)NULL; + TC_MUTEX_LOCK(mut); + rv = g_malloc(len, z); + TC_MUTEX_UNLOCK(mut); + return rv; +} + +void t_free(void * mut, void * p) { + if (p != NULL) { + TC_MUTEX_LOCK(mut); + g_free(p); + TC_MUTEX_UNLOCK(mut); + } + return; +} + + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/thread_calls.h posixrdp/posixxrdp.orig/common/thread_calls.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/thread_calls.h 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/thread_calls.h 2010-11-08 09:56:43.000000000 +0100 @@ -26,29 +26,284 @@ #if !defined(THREAD_CALLS_H) #define THREAD_CALLS_H +#include +#include +#include +#include +#include +#include +#include #include "arch.h" +#include "thread_macros.h" -int APP_CC +#ifndef MAX_MUTEX +#define MAX_MUTEX 25 +#endif + + +#if defined(_WIN32) + #if !defined(MAX_EVENTS) + #define MAX_EVENTS 256 + #endif +typedef HANDLE pthread_t; +typedef HANDLE sem_t; +typedef HANDLE pthread_mutex_t; +typedef int pthread_condattr_t; +typedef int pthread_attr_t; +typedef int pthread_mutex_t; +typedef struct _WIN32_pthread_cond_t { + int waiters_count_; + // Number of waiting threads. + + CRITICAL_SECTION waiters_count_lock_; + // Serialize access to . + + HANDLE sema_; + // Semaphore used to queue up threads waiting for the condition to + // become signaled. + + HANDLE waiters_done_; + // An auto-reset event used by the broadcast/signal thread to wait + // for all the waiting thread(s) to wake up and be released from the + // semaphore. + + size_t was_broadcast_; + // Keeps track of whether we were broadcasting or signaling. This + // allows us to optimize the code if we're just signaling. +} pthread_cond_t; +#endif + +#define TC_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE +#define TC_CREATE_DETACHED PTHREAD_CREATE_DETACHED +#define TC_SCOPE_SYSTEM PTHREAD_SCOPE_SYSTEM +#define TC_SCOPE_PROCESS PTHREAD_SCOPE_PROCESS +#define TC_PROCESS_PRIVATE PTHREAD_PROCESS_PRIVATE +#define TC_PROCESS_SHARED PTHREAD_PROCESS_SHARED + +#define TC_MUTEX_INITIALIZER { .mut = PTHREAD_MUTEX_INITIALIZER } +#define TC_RWLOCK_INITIALIZER { .rwlock = PTHREAD_RWLOCK_INITIALIZER } +#define TC_COND_INITIALIZER { .cond = PTHREAD_COND_INITIALIZER } +#define TC_SPIN_INITIALIZER { .spin = 0 } + +#if defined(PTHREAD_MUTEX_ERRORCHECK) +#define TC_MUTEX_ERRORCHECK PTHREAD_MUTEX_ERRORCHECK +#else +#define TC_MUTEX_ERRORCHECK PTHREAD_MUTEX_ERRORCHECK_NP +#endif +#define TC_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE +#define TC_MUTEX_NORMAL PTHREAD_MUTEX_NORMAL +#define TC_MUTEX_DEFAULT PTHREAD_MUTEX_DEFAULT + + +typedef tbus tc_thread_t; +typedef sem_t tc_sem_t; +typedef pthread_attr_t tc_threadattr_t; +typedef pthread_mutex_t tc_mut_t; +typedef pthread_mutexattr_t tc_mutattr_t; +typedef pthread_cond_t tc_cond_t; +typedef pthread_condattr_t tc_condattr_t; +typedef pthread_rwlock_t tc_rwlock_t; +typedef pthread_rwlockattr_t tc_rwlockattr_t; +typedef pthread_key_t tc_key_t; +typedef struct timespec tc_datetime_t; +typedef int tc_future_t; + +#ifdef __USE_XOPEN2K +typedef pthread_barrier_t tc_barr_t; +typedef pthread_barrierattr_t tc_barrattr_t; +typedef pthread_spinlock_t tc_spin_t; +#endif + +#define TC_THREAD_T tbus +#define TC_SEM_T sem_t +#define TC_THREADATTR_T pthread_attr_t +#define TC_MUT_T pthread_mutex_t +#define TC_MUTATTR_T pthread_mutexattr_t +#define TC_COND_T pthread_cond_t +#define TC_CONDATTR_T pthread_condattr_t +#define TC_RWLOCK_T pthread_rwlock_t +#define TC_RWLOCKATTR_T pthread_rwlockattr_t +#define TC_KEY_T pthread_key_t + +#ifdef __USE_XOPEN2K +#define TC_BARR_T pthread_barrier_t +#define TC_BARRATTR_T pthread_barrierattr_t +#define TC_SPIN_T pthread_spinlock_t +#endif + +typedef struct tc_val { + #define TC_RETVAL_MAGIC 0xacedf001 + uint32_t magic; + tc_thread_t thread; + unsigned long len; + uint8_t data[]; +} tc_retval_t, *tc_retval_p, tc_args_t, *tc_args_p, tc_val, *tc_val_p; + +typedef union tc_union { + tc_sem_t sem; + tc_thread_t thread; + tc_threadattr_t threadattr; + tc_mut_t mut; + tc_mutattr_t mutattr; + tc_cond_t cond; + tc_condattr_t condattr; + tc_rwlock_t rwlock; + tc_rwlockattr_t rwlockattr; + tc_key_t key; + tc_retval_t retval; +#ifdef __USE_XOPEN2K + tc_barr_t barrier; + tc_barrattr_t barrattr; + tc_spin_t spin; +#endif +} tc_t, *tc_p; + + + +tc_thread_t APP_CC tc_thread_create(THREAD_RV (THREAD_CC * start_routine)(void*), void* arg); -tbus APP_CC +int APP_CC +tc_thread_init_full(tc_thread_t *, const tc_threadattr_t *, void * (* start_routine)(void *), void *); +int APP_CC +tc_thread_init(tc_thread_t *, THREAD_RV (THREAD_CC * start_routine)(void*), void *); +int APP_CC +tc_thread_join(tc_thread_t, void **); +int APP_CC +tc_thread_detach(tc_thread_t); +void APP_CC +tc_thread_exit(void *); +int APP_CC +tc_thread_signal(tc_thread_t, int); +tc_thread_t APP_CC tc_get_threadid(void); int APP_CC -tc_threadid_equal(tbus tid1, tbus tid2); -tbus APP_CC +tc_threadid_equal(tc_thread_t, tc_thread_t); +tc_p APP_CC tc_mutex_create(void); -void APP_CC -tc_mutex_delete(tbus mutex); int APP_CC -tc_mutex_lock(tbus mutex); +tc_mutex_init(tc_p, tc_p); /* (tc_mut_t *, tc_mutattr_t *) */ +int APP_CC +tc_mutex_delete(tc_p mutex); +int APP_CC +tc_mutex_deinit(tc_p mutex); int APP_CC -tc_mutex_unlock(tbus mutex); -tbus APP_CC +tc_mutex_lock(tc_p mutex); +int APP_CC +tc_mutex_unlock(tc_p mutex); +int APP_CC +tc_mutex_timedlock(tc_p, const struct timespec *); +int APP_CC +tc_mutexattr_init(tc_p); +int APP_CC +tc_mutexattr_destroy(tc_p); +int APP_CC +tc_mutexattr_gettype(tc_p); +int APP_CC +tc_mutexattr_getprotocol(tc_p); +int APP_CC +tc_mutexattr_getpshared(tc_p); +int APP_CC +tc_mutexattr_settype(tc_p, int); +int APP_CC +tc_mutexattr_setprotocol(tc_p, int); +int APP_CC +tc_mutexattr_setpshared(tc_p, int); +tc_p APP_CC tc_sem_create(int init_count); void APP_CC -tc_sem_delete(tbus sem); +tc_sem_delete(tc_p sem); +void APP_CC +tc_sem_deinit(tc_p sem); int APP_CC -tc_sem_dec(tbus sem); +tc_sem_dec(tc_p sem); int APP_CC -tc_sem_inc(tbus sem); +tc_sem_inc(tc_p sem); +int APP_CC +tc_cond_create(tc_p, const tc_p); /* (tc_cond_t *, tc_condattr_t *) */ +int APP_CC +tc_cond_wait(tc_p, tc_p); /* (tc_cond_t *, tc_mutex_t *) */ +int APP_CC +tc_cond_timedwait(tc_p, tc_p, tc_future_t); /* (tc_cond_t *, tc_mutex_t *, tc_future_t) */ +int APP_CC +tc_cond_signal(tc_p); +int APP_CC +tc_cond_broadcast(tc_p); +int APP_CC +tc_cond_delete(tc_p); +int APP_CC +tc_cond_deinit(tc_p); + +int APP_CC +tc_condattr_init(tc_p); +int APP_CC +tc_condattr_deinit(tc_p); +int APP_CC +tc_condattr_getpshared(const tc_p, int *); +int APP_CC +tc_condattr_setpshared(tc_p, int); + +int APP_CC +tc_spin_init(tc_p); +int APP_CC +tc_spin_destroy(tc_p); +int APP_CC +tc_spin_deinit(tc_p); +int APP_CC +tc_spin_lock(tc_p); +int APP_CC +tc_spin_unlock(tc_p); +int APP_CC +tc_spin_trylock(tc_p); + +int APP_CC +tc_barrattr_init(tc_p); +int APP_CC +tc_barrattr_setpshared(tc_p, int); +int APP_CC +tc_barrier_init(tc_p, int); +int APP_CC +tc_barrier_init_full(tc_p, tc_p, int); +int APP_CC +tc_barrier_deinit(tc_p); +int APP_CC +tc_barrier_wait(tc_p); + +int APP_CC +tc_threadattr_init(tc_p); +int APP_CC +tc_threadattr_getdetachstate(const tc_p, int *); +int APP_CC +tc_threadattr_setdetachstate(tc_p, int); +int APP_CC +tc_threadattr_getscope(const tc_p, int *); +int APP_CC +tc_threadattr_setscope(tc_p, int); +int APP_CC +tc_threadattr_setstacksize(tc_p, size_t); +int APP_CC +tc_threadattr_getstacksize(tc_p, size_t *); + +int APP_CC +tc_mutattr_init(tc_p); +int APP_CC +tc_mutattr_settype(tc_p, int); +int APP_CC +tc_mutattr_gettype(tc_p attr); +int APP_CC +tc_mutattr_setpshared(tc_p, int); +int APP_CC +tc_mutattr_getpshared(const tc_p, int *); +int APP_CC +tc_mutattr_setprotocol(tc_p, int); +int APP_CC +tc_mutattr_getprotocol(tc_p); +int APP_CC +tc_mutattr_destroy(tc_p); + +int APP_CC tc_mutex_trylock(tc_p); + +void * t_malloc(void *, size_t, unsigned char); +void t_free(void *, void *); + #endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/thread_macros.h posixrdp/posixxrdp.orig/common/thread_macros.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/thread_macros.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/thread_macros.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,190 @@ +#include "thread_calls.h" + +#ifndef __XRDP_TC_MACROS__ +#define __XRDP_TC_MACROS__ + +//# d efine DISABLE_THREADS_ +//# d efine ENABLE_SPINLOCKS_ +//# d efine DEBUG_THREADS_ + +#if defined(DISABLE_THREADS) + #define TC_THREAD_CREATE(x,y,z) ; + #define TC_THREAD_INIT(x,y,z) ; + #define TC_THREAD_INIT_FULL(w,x,y,z) ; + #define TC_THREAD_JOIN(x) ; + #define TC_THREADATTR_INIT(x) ; + #define TC_THREADATTR_SETDETACHSTATE(x,y) ; + #define TC_THREADATTR_SETPSHARED(x,y) ; + #define TC_THREADATTR_SETSTACKSIZE(x,y) ; + #define TC_THREADATTR_GETSTACKSIZE(x,y) ; + #define TC_THREADATTR_DEINIT(x) ; + #define TC_MUTEX_INIT(x, y) ; + #define TC_MUTEX_DEINIT(x) ; + #define TC_MUTEX_LOCK(x) ; + #define TC_MUTEX_UNLOCK(x) ; + #define TC_MUTEX_TRYLOCK(x) ; + #define TC_MUTEX_TIMEDLOCK(x, y) ; + #define TC_SPIN_INIT(x) ; + #define TC_SPIN_DEINIT(x) ; + #define TC_SPIN_LOCK(x) ; + #define TC_SPIN_UNLOCK(x) ; + #define TC_COND_CREATE(x, y) ; + #define TC_COND_WAIT(x, y) ; + #define TC_COND_TIMEDWAIT(x, y, z) ; + #define TC_COND_SIGNAL(x) ; + #define TC_COND_BROADCAST(x) ; + #define TC_COND_DELETE(x) ; + #define TC_COND_DEINIT(x) ; + #define TC_BARRATTR_INIT(x) ; + #define TC_BARRATTR_SETPSHARED(x,y) ; + #define TC_BARR_INIT(x,y) ; + #define TC_BARR_DEINIT(x) ; + #define TC_BARR_WAIT(x) ; + #define TC_THREAD_EXIT(x) ; + #define TC_THREAD_KILL(x) ; +#else + #if defined(ENABLE_SPINLOCKS) + #define TC_THREAD_CREATE(x,y,z) tc_thread_init(x,y,z) + #define TC_THREAD_INIT(x,y,z) tc_thread_init(x,y,z) + #define TC_THREAD_INIT_FULL(w,x,y,z) tc_thread_init_full(w,x,y,z) + #define TC_THREAD_EXIT(x) tc_thread_exit((tc_p)x) + #define TC_THREAD_JOIN(x) tc_thread_join(x) + #define TC_THREAD_KILL(x) tc_thread_signal(x,SIGTERM) + #define TC_THREADATTR_INIT(x) tc_threadattr_init(x) + #define TC_THREADATTR_SETDETACHSTATE(x,y) tc_threadattr_setdetachstate(x,y) + #define TC_THREADATTR_SETPSHARED(x,y) tc_threadattr_setpshared(x,y) + #define TC_THREADATTR_SETSTACKSIZE(x,y) tc_threadattr_setstacksize(x,y); + #define TC_THREADATTR_GETSTACKSIZE(x,y) tc_threadattr_getstacksize(x,y); + #define TC_THREADATTR_DEINIT(x) tc_threadattr_deinit(x) + #define TC_MUTEX_INIT(x, y) tc_spin_init((tc_p)x) + #define TC_MUTEX_LOCK(x) tc_spin_lock((tc_p)x) + #define TC_MUTEX_UNLOCK(x) tc_spin_unlock((tc_p)x) + #define TC_MUTEX_DEINIT(x) tc_spin_destroy((tc_p)x) + #define TC_MUTEX_TRYLOCK(x) tc_spin_trylock((tc_p)x) + #define TC_MUTEX_TIMEDLOCK(x) tc_spin_timedlock((tc_p)x) + #define TC_COND_CREATE(x, y) tc_cond_create((tc_p)x, y) + #define TC_COND_WAIT(x, y) tc_cond_wait((tc_p)x, y) + #define TC_COND_TIMEDWAIT(x, y, z) tc_cond_timedwait((tc_p)x, y, z) + #define TC_COND_SIGNAL(x) tc_cond_signal((tc_p)x) + #define TC_COND_BROADCAST(x) tc_cond_broadcast((tc_p)x) + #define TC_COND_DELETE(x) tc_cond_delete((tc_p)x) + #define TC_COND_DEINIT(x) tc_cond_deinit((tc_p)x) +#if defined(__USE_XOPEN2K) + #define TC_BARRATTR_INIT(x) tc_barrattr_init((tc_p)x) + #define TC_BARRATTR_SETPSHARED(x,y) tc_barrattr_setpshared((tc_p)x, y) + #define TC_BARR_INIT(x,y) tc_barrier_init((tc_p)x, y) + #define TC_BARR_INIT_FULL(x,y,z) tc_barrier_init_full((tc_p)x, (tc_p)y, z) + #define TC_BARR_DEINIT(x) tc_barrier_deinit((tc_p)x) + #define TC_BARR_WAIT(x) tc_barrier_wait((tc_p)x) + #define TC_SPIN_INIT(x) tc_spin_init(x) + #define TC_SPIN_DEINIT(x) tc_spin_deinit(x) + #define TC_SPIN_LOCK(x) tc_spin_lock(x) + #define TC_SPIN_UNLOCK(x) tc_spin_unlock(x) +#else + #define TC_BARR_INIT(x,y) 0 + #define TC_BARR_INIT_FULL(x,y,z) 0 + #define TC_BARR_DEINIT(x) 0 + #define TC_BARR_WAIT(x) 0 + #define TC_SPIN_INIT(x) 0 + #define TC_SPIN_DEINIT(x) 0 + #define TC_SPIN_LOCK(x) 0 + #define TC_SPIN_UNLOCK(x) 0 +#endif + #else + #define TC_THREAD_CREATE(x,y,z) tc_thread_init(x,y,z) + #define TC_THREAD_INIT(x,y,z) tc_thread_init(x,y,z) + #define TC_THREAD_INIT_FULL(w,x,y,z) tc_thread_init_full(w,x,y,z) + #define TC_THREAD_EXIT(x) tc_thread_exit((tc_p)x) + #define TC_THREAD_JOIN(x,y) tc_thread_join(x,y) + #define TC_THREAD_KILL(x) tc_thread_signal(x,SIGTERM) + #define TC_THREADATTR_INIT(x) tc_threadattr_init(x) + #define TC_THREADATTR_SETDETACHSTATE(x,y) tc_threadattr_setdetachstate(x,y) + #define TC_THREADATTR_SETPSHARED(x,y) tc_threadattr_setpshared(x,y) + #define TC_THREADATTR_SETSTACKSIZE(x,y) tc_threadattr_setstacksize(x,y); + #define TC_THREADATTR_GETSTACKSIZE(x,y) tc_threadattr_getstacksize(x,y); + #define TC_THREADATTR_DEINIT(x) tc_threadattr_deinit(x) + #define TC_MUTEX_INIT(x, y) tc_mutex_init((tc_p)x, (tc_p)y) + #define TC_MUTEX_LOCK(x) if (x != NULL) { tc_mutex_lock((tc_p)x); } + #define TC_MUTEX_UNLOCK(x) if (x != NULL) { tc_mutex_unlock((tc_p)x); } + #define TC_MUTEX_DEINIT(x) if (x != NULL) { tc_mutex_deinit((tc_p)x); } + #define TC_MUTEX_TRYLOCK(x) tc_mutex_trylock((tc_p)x) + #define TC_MUTEX_TIMEDLOCK(x, y) tc_mutex_timedlock((tc_p)x, (const struct timespec *)y) + #define TC_MUTATTR_INIT(x) tc_mutattr_init((tc_p)x) + #define TC_MUTATTR_DEINIT(x) tc_mutattr_destroy((tc_p)x) + #define TC_MUTATTR_GETTYPE(x) tc_mutattr_gettype((tc_p)x) + #define TC_MUTATTR_GETPROTOCOL(x) tc_mutattr_getprotocol((tc_p)x) + #define TC_MUTATTR_GETPSHARED(x, y) tc_mutattr_getpshared((const tc_p)x, (int *)y) + #define TC_MUTATTR_SETTYPE(x, y) tc_mutattr_settype((tc_p)x, (int)y) + #define TC_MUTATTR_SETPROTOCOL(x, y) tc_mutattr_setprotocol((tc_p)x, (int)y) + #define TC_MUTATTR_SETPSHARED(x, y) tc_mutattr_setpshared((const tc_p)x, (int)y) + #define TC_SPIN_INIT(x) TC_MUTEX_INIT(x,NULL) + #define TC_SPIN_DEINIT(x) TC_MUTEX_DEINIT(x) + #define TC_SPIN_LOCK(x) TC_MUTEX_LOCK(x) + #define TC_SPIN_UNLOCK(x) TC_MUTEX_UNLOCK(x) + #define TC_CONDATTR_INIT(x) tc_condattr_init((tc_p)x) + #define TC_CONDATTR_DEINIT(x) tc_condattr_destroy((tc_p)x) + #define TC_CONDATTR_GETPSHARED(x, y) tc_condattr_getpshared((const tc_p)x, (int *)y) + #define TC_CONDATTR_SETPSHARED(x, y) tc_condattr_setpshared((const tc_p)x, (int)y) + #define TC_COND_CREATE(x, y) tc_cond_create((tc_p)x, y) + #define TC_COND_WAIT(x, y) tc_cond_wait((tc_p)x, y) + #define TC_COND_TIMEDWAIT(x, y, z) tc_cond_timedwait((tc_p)x, y, z) + #define TC_COND_SIGNAL(x) tc_cond_signal((tc_p)x) + #define TC_COND_BROADCAST(x) tc_cond_broadcast((tc_p)x) + #define TC_COND_DELETE(x) tc_cond_delete((tc_p)x) + #define TC_COND_DEINIT(x) tc_cond_deinit((tc_p)x) +#if defined(__USE_XOPEN2K) + #define TC_BARRATTR_INIT(x) tc_barrattr_init((tc_p)x) + #define TC_BARRATTR_SETPSHARED(x,y) tc_barrattr_setpshared((tc_p)x, y) + #define TC_BARR_INIT(x,y) tc_barrier_init((tc_p)x, y) + #define TC_BARR_INIT_FULL(x,y,z) tc_barrier_init_full((tc_p)x, (tc_p)y, z) + #define TC_BARR_DEINIT(x) tc_barrier_deinit((tc_p)x) + #define TC_BARR_WAIT(x) tc_barrier_wait((tc_p)x) +#else + #define TC_BARR_INIT(x,y) 0 + #define TC_BARR_INIT_FULL(x,y,z) 0 + #define TC_BARR_DEINIT(x) 0 + #define TC_BARR_WAIT(x) 0 + #define TC_SPIN_INIT(x) 0 + #define TC_SPIN_DEINIT(x) 0 + #define TC_SPIN_LOCK(x) 0 + #define TC_SPIN_UNLOCK(x) 0 +#endif + #endif + + #if defined(DEBUG_THREADS) + #undef TC_MUTEX_LOCK + #undef TC_MUTEX_UNLOCK + #undef TC_MUTEX_TRYLOCK + #undef TC_MUTEX_TIMEDLOCK + #define TC_MUTEX_LOCK(x) ; + #define TC_MUTEX_UNLOCK(x) ; + #define TC_MUTEX_TRYLOCK(x) ; + #define TC_MUTEX_TIMEDLOCK(x, y) ; + /* + #define TC_THREAD_CREATE(x,y,z) tc_thread_init(x,y,z) + #define TC_THREAD_INIT(x,y,z) tc_thread_init(x,y,z) + #define TC_THREAD_INIT_FULL(w,x,y,z) tc_thread_init_full(w,x,y,z) + #define TC_MUTEX_LOCK(x) pthread_mutex_lock(x) + #define TC_MUTEX_UNLOCK(x) pthread_mutex_unlock(x) + #define TC_MUTEX_TRYLOCK(x) pthread_mutex_trylock(x) + #define TC_MUTEX_TIMEDLOCK(x, y) pthread_mutex_timedlock(x, y) + */ + #endif + +#endif + +#if defined(__linux__) +#if defined(ARM) +typedef void (__kernel_dmb_t) (void); +#define __kernel_dmb (*(__kernel_dmb_t *) 0xffff0fa0) +#define MEM_BARRIER __kernel_dmb() +#else +#define MEM_BARRIER __sync_synchronize() +#endif +#else +#define MEM_BARRIER {} +#endif +#define MB MEM_BARRIER + + +#endif /* __XRDP_TC_MACROS__ */ diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/trans.c posixrdp/posixxrdp.orig/common/trans.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/trans.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/trans.c 2010-11-08 09:56:43.000000000 +0100 @@ -23,49 +23,74 @@ */ +#include +#include +#include +#include +#include #include "os_calls.h" #include "trans.h" #include "arch.h" #include "parse.h" +#include "dbg.h" -/*****************************************************************************/ -struct trans* APP_CC -trans_create(int mode, int in_size, int out_size) -{ - struct trans* self; +#if defined(__XRDP_TRANS_LOCKS__) +#undef __XRDP_TRANS_LOCKS__ +#endif + +#if 0 +#if defined(MDBGLOG) +#undef MDBGLOG +#define MDBGLOG(...) ; +#endif +#endif - self = (struct trans*)g_malloc(sizeof(struct trans), 1); - make_stream(self->in_s); - init_stream(self->in_s, in_size); - make_stream(self->out_s); - init_stream(self->out_s, out_size); - self->mode = mode; + +/*****************************************************************************/ +struct trans * APP_CC +trans_create(int mode, size_t in_size, size_t out_size) { + struct trans * self = (struct trans *)NULL; + + // MDBGLOG("trans","INFO\t[%s()]: called [%d, %d]",__func__,g_getpid(),g_gettid()); + + self = (struct trans *)g_malloc(sizeof(struct trans), 1); + if (self != NULL) { + make_stream(self->in_s); + init_stream(self->in_s, in_size); + make_stream(self->out_s); + init_stream(self->out_s, out_size); + self->mode = mode; + } return self; } /*****************************************************************************/ void APP_CC -trans_delete(struct trans* self) -{ - if (self == 0) - { +trans_delete(struct trans * self) { + // MDBGLOG("trans","INFO\t[%s()]: called (self = %p) [%d, %d]",__func__,self,g_getpid(),g_gettid()); + if (self == 0) { + // MDBGLOG("trans","WARNING\t[%s()]: self is NULL",__func__); return; } free_stream(self->in_s); free_stream(self->out_s); - g_tcp_close(self->sck); + if (self->sck > 0) { + g_tcp_close(self->sck); + } + self->sck = 0; if (self->listen_filename != 0) { g_file_delete(self->listen_filename); g_free(self->listen_filename); } - g_free(self); + // MDBGLOG("trans","INFO\t[%s()]: done.",__func__); } /*****************************************************************************/ int APP_CC -trans_get_wait_objs(struct trans* self, tbus* objs, int* count, int* timeout) -{ +trans_get_wait_objs(struct trans * self, tbus objs[], ptrdiff_t * count, int * timeout) { + // MDBGLOG("trans","INFO\t[%s()]: called [%d, %d]",__func__,g_getpid(),g_gettid()); + if (self == 0) { return 1; @@ -74,52 +99,87 @@ { return 1; } - objs[*count] = self->sck; + objs[(*count)] = self->sck; (*count)++; + if (0 && (self->mode == 0 || self->mode == 3) && self->sck_out > 0) { + objs[(*count)] = self->sck_out; + (*count)++; + } + + // MDBGLOG("trans","INFO\t[%s()]: done.",__func__); + return 0; } /*****************************************************************************/ int APP_CC -trans_check_wait_objs(struct trans* self) -{ - tbus in_sck; - struct trans* in_trans; - int read_bytes; - int to_read; - int read_so_far; - int rv; +trans_check_wait_objs(struct trans * self) { + tbus in_sck = (tbus)0; + struct trans* in_trans = (struct trans *)NULL; + ptrdiff_t read_bytes = 0; + ptrdiff_t to_read = 0; + ptrdiff_t read_so_far = 0; + int rv = 0; + int tmp = 0; if (self == 0) { - return 1; + MDBGLOG("chansrv","ERROR\t[%s()]: self == 0",__func__); + rv = 1; + goto end; } if (self->status != 1) { - return 1; + // MDBGLOG("chansrv","ERROR\t[%s()]: self->status is not equal to 1",__func__); + rv = 1; + goto end; } rv = 0; if (self->type1 == 1) /* listening */ { - if (g_tcp_can_recv(self->sck, 0)) + if ((self->mode == 0 || self->mode == 3) && g_fifo_can_read(self->sck, 0)) { + in_sck = self->sck; + if (in_sck == -1) { + } + else { + if (self->trans_conn_in != NULL) { /* is function assigned */ + in_trans = trans_create(self->mode, self->in_s->size, + self->out_s->size); + in_trans->sck = in_sck; + in_trans->type1 = 2; + in_trans->status = 1; + if (self->trans_conn_in(self, in_trans) != 0) + { + trans_delete(in_trans); + } + } + else { + g_tcp_close(in_sck); + } + } + } + else if ((self->mode == 1 || self->mode == 2) && g_tcp_can_recv(self->sck, 0)) { in_sck = g_tcp_accept(self->sck); if (in_sck == -1) { + // MDBGLOG("chansrv","INFO\t[%s()]: g_tcp_accept() returned -1",__func__); if (g_tcp_last_error_would_block(self->sck)) { /* ok, but shouldn't happen */ + // MDBGLOG("chansrv","INFO\t[%s()]: last error would block (\"ok, but shouldn't happen\")",__func__); } else { /* error */ self->status = 0; rv = 1; + MDBGLOG("chansrv","ERROR\t[%s()]: g_tcp_last_error_would_block(self->sck)",__func__); } } if (in_sck != -1) { - if (self->trans_conn_in != 0) /* is function assigned */ + if (self->trans_conn_in != NULL) /* is function assigned */ { in_trans = trans_create(self->mode, self->in_s->size, self->out_s->size); @@ -140,64 +200,110 @@ } else /* connected server or client (2 or 3) */ { - if (g_tcp_can_recv(self->sck, 0)) + if (self->mode == 0) { + tmp = g_fifo_can_read(self->sck, 0); + } + if (self->mode == 3) { + tmp = g_fifo_can_read(self->sck, 0); + } + else { + tmp = g_tcp_can_recv(self->sck, 0); + } + if (tmp > 0) { - read_so_far = (int)(self->in_s->end - self->in_s->data); + read_so_far = self->in_s->end - self->in_s->data; to_read = self->header_size - read_so_far; - read_bytes = g_tcp_recv(self->sck, self->in_s->end, to_read, 0); + if (self->mode == 3 || self->mode == 0) { + if (to_read > 0) { + read_bytes = g_fifo_read(self->sck, self->in_s->end, to_read); + } + else { + read_bytes = 0; + } + } + else if (to_read > 0) { + read_bytes = g_tcp_recv(self->sck, self->in_s->end, to_read, 0); + } + else { + read_bytes = 0; + } if (read_bytes == -1) { + // MDBGLOG("chansrv","INFO\t[%s()]: read_bytes = -1",__func__); if (g_tcp_last_error_would_block(self->sck)) { /* ok, but shouldn't happen */ + // MDBGLOG("chansrv","INFO\t[%s()]: g_tcp_last_error_would_block() returned -1 (\"ok, but shouldn't happen\")",__func__); } else { /* error */ self->status = 0; rv = 1; + MDBGLOG("chansrv","ERROR\t[%s()]: read_bytes == -1 and g_tcp_last_error_would_block(self->sck) is false",__func__); } } - else if (read_bytes == 0) - { - /* error */ - self->status = 0; - rv = 1; + else if (read_bytes == 0 && self->header_size > 0) { + /* error */ + self->status = 0; + rv = 1; + MDBGLOG("chansrv","ERROR\t[%s()]: read_bytes == 0 and self->header_size > 0",__func__); } - else - { - self->in_s->end += read_bytes; + else { + self->in_s->end += read_bytes; } read_so_far = (int)(self->in_s->end - self->in_s->data); - if (read_so_far == self->header_size) - { - if (self->trans_data_in != 0) - { - rv = self->trans_data_in(self); - init_stream(self->in_s, 0); - } + if (read_so_far == self->header_size && self->trans_data_in != NULL) { + rv = self->trans_data_in(self); + init_stream(self->in_s, 0); } } } + end:; + if (rv != 0) { + // MDBGLOG("chansrv","ERROR\t[%s()]: rv = %d",__func__,rv); + } return rv; } /*****************************************************************************/ -int APP_CC -trans_force_read(struct trans* self, int size) +ptrdiff_t APP_CC +trans_force_read(struct trans* self, size_t size) { - int rv; - int rcvd; + ptrdiff_t rv = 0; + ptrdiff_t rcvd = 0; + time_t start_timestamp = 0; + time_t current_timestamp = 0; + time_t previous_timestamp = 0; + unsigned int elapsed = 0; + + if (self == NULL) { + rv = 1; + goto end; + } + + start_timestamp = time(NULL); + previous_timestamp = 0; + current_timestamp = start_timestamp; + elapsed = current_timestamp - start_timestamp; + rv = 0; if (self->status != 1) { - return 1; + rv = 1; } - rv = 0; - while (size > 0) - { - rcvd = g_tcp_recv(self->sck, self->in_s->end, size, 0); - if (rcvd == -1) + else while (size > 0) + { + if (self->mode == 0) { + rcvd = g_file_read(self->sck, self->in_s->end, size); + } + else if (self->mode == 3) { + rcvd = g_fifo_read(self->sck, self->in_s->end, size); + } + else if (self->mode == 1 || self->mode == 2) { + rcvd = g_tcp_recv(self->sck, self->in_s->end, size, 0); + } + if (rcvd == -1 && self->mode != 3) { if (g_tcp_last_error_would_block(self->sck)) { @@ -224,46 +330,58 @@ self->in_s->end += rcvd; size -= rcvd; } + } + + end:; return rv; } /*****************************************************************************/ -int APP_CC -trans_force_write(struct trans* self) +ptrdiff_t APP_CC +trans_read(struct trans* self, size_t size) { - int size; - int total; - int rv; - int sent; + ptrdiff_t rv = 0; + ptrdiff_t rcvd = 0; + int cont = 1; - if (self->status != 1) - { - return 1; + // MDBGLOG("trans","INFO\t[%s()]: called (size = %d, self->sck = %d) [%d, %d]",__func__,size,(int)self->sck,g_getpid(),g_gettid()); + + if (self == NULL) { + rv = -1; + goto end; } - rv = 0; - size = (int)(self->out_s->end - self->out_s->data); - total = 0; - while (total < size) - { - sent = g_tcp_send(self->sck, self->out_s->data + total, size - total, 0); - if (sent == -1) - { - if (g_tcp_last_error_would_block(self->sck)) - { - if (!g_tcp_can_send(self->sck, 10)) + + if (self->status != 1) { + rv = -2; + goto end; + } + else while (cont > 0) { + cont = 0; + if (self->mode == 0) { + rcvd = g_file_read(self->sck, self->in_s->end, size); + } + else if (self->mode == 3) { + rcvd = g_fifo_read(self->sck, self->in_s->end, size); + } + else if (self->mode == 1 || self->mode == 2) { + rcvd = g_tcp_recv(self->sck, self->in_s->end, size, 0); + } + if (rcvd == -1 && self->mode != 3 && self->mode != 0) { + if (g_tcp_last_error_would_block(self->sck)) { + if (!g_tcp_can_recv(self->sck, 10)) { /* check for term here */ } + cont = 1; } - else - { + else { /* error */ self->status = 0; rv = 1; } } - else if (sent == 0) + else if (rcvd == 0) { /* error */ self->status = 0; @@ -271,9 +389,121 @@ } else { - total = total + sent; + self->in_s->end += rcvd; + size -= rcvd; + } + if (size < 1 ) { + cont = 0; } } + rv = (rcvd > -1) ? (size_t)(rcvd) : 0; + + end:; + // MDBGLOG("trans","INFO\t[%s()]: done (read %d bytes).", __func__, rv); + return rv; +} + +/*****************************************************************************/ +ptrdiff_t APP_CC +trans_force_write(struct trans* self) { + ptrdiff_t size = 0; + ptrdiff_t total = 0; + ptrdiff_t rv = 0; + ptrdiff_t sent = 0; + time_t start_timestamp = 0; + time_t current_timestamp = 0; + time_t previous_timestamp = 0; + unsigned int elapsed = 0; + + if (self == NULL || self->sck < 1) { + rv = -1; + MDBGLOG("chansrv","ERROR\t[%s() @ line %d]: not ready",__func__,__LINE__); + goto end; + } + + start_timestamp = time(NULL); + previous_timestamp = 0; + current_timestamp = start_timestamp; + elapsed = current_timestamp - start_timestamp; + + if (self->status != 1) { + rv = -5; + MDBGLOG("chansrv","ERROR\t[%s() @ line %d]: status is not ready",__func__,__LINE__); + goto end; + } + else { + rv = 0; + size = self->out_s->end - self->out_s->data; + total = 0; + while (total < size) { + sent = 0; + if (self->mode == 0) { + if (self->sck_out != 0) { + sent = g_file_write(self->sck_out, (self->out_s->data + total), (size - total)); + } + else { + sent = g_file_write(self->sck, (self->out_s->data + total), (size - total)); + } + } + else if (self->mode == 3) { + if (self->sck_out != 0) { + sent = g_fifo_write(self->sck_out, (self->out_s->data + total), (size - total)); + } + else { + sent = g_fifo_write(self->sck, (self->out_s->data + total), (size - total)); + } + } + else if ((self->mode == 1 || self->mode == 2) && !g_tcp_socket_ok(self->sck)) { + MDBGLOG("chansrv","WARNING\t[%s()]: self->sck is not OK",__func__); + continue; + } + else if (g_tcp_can_send(self->sck, 50)) { + sent = g_tcp_send_force(self->sck, (self->out_s->data + total), (size - total), self->send_flags); + } + else { + MDBGLOG("chansrv","ERROR\t[%s() @ line %d]: failed",__func__,__LINE__); + } + if (current_timestamp != previous_timestamp) { + // MDBGLOG("trans","INFO\t[%s()]: [%d] total = %d (out of %d); sent = %d; self->sck = %d ...",__func__,elapsed,total,size,sent,self->sck); + } + if (sent == -1) { + if (g_tcp_last_error_would_block(self->sck)) { + if (!g_tcp_can_send(self->sck, 10)) { + /* check for term here */ + } + } + else { + /* error */ + self->status = 0; + rv = -2; + MDBGLOG("chansrv","ERROR\t[%s() @ line %d]: sent = -1",__func__,__LINE__); + } + } + else if (sent == 0) { + /* error */ + self->status = 0; + rv = -3; + MDBGLOG("chansrv","ERROR\t[%s() @ line %d]: sent = 0",__func__,__LINE__); + } + else { + total = total + sent; + if (total >= size) { + break; + } + } + previous_timestamp = current_timestamp; + current_timestamp = time(NULL); + elapsed = current_timestamp - start_timestamp; + } + } + + if (elapsed > 4) { + // MDBGLOG("trans","WARNING\t[%s()]: timed out! total = %d",__func__,total); + MDBGLOG("chansrv","WARNING\t[%s() @ line %d]: timed out (total = %d)",__func__,__LINE__,total); + rv = -4; + } + + end:; return rv; } @@ -282,27 +512,41 @@ trans_connect(struct trans* self, const char* server, const char* port, int timeout) { - int error; + int error = 0; - if (self->sck != 0) - { + // MDBGLOG("trans","INFO\t[%s()]: called (server = %s; port = %s; timeout = %d; self->mode = %d; self->sck = %d) [%d, %d]",__func__,server,port,timeout,self->mode,self->sck,g_getpid(),g_gettid()); + + if (self == NULL) { + return -1; + } + + if (self->sck != 0 && self->mode == 3) { + g_file_close(self->sck); + } + else if (self->sck != 0 && self->mode != 3) { g_tcp_close(self->sck); } - if (self->mode == 1) /* tcp */ - { + if (self->mode == 0) { /* stdin/stdout */ + self->sck = fcntl(STDIN_FILENO, F_DUPFD); + self->sck_out = fcntl(STDOUT_FILENO, F_DUPFD); + } + if (self->mode == 1) { /* tcp */ self->sck = g_tcp_socket(); g_tcp_set_non_blocking(self->sck); error = g_tcp_connect(self->sck, server, port); } - else if (self->mode == 2) /* unix socket */ - { + else if (self->mode == 2) { /* unix socket */ self->sck = g_tcp_local_socket(); g_tcp_set_non_blocking(self->sck); error = g_tcp_local_connect(self->sck, port); } - else - { + else if (self->mode == 3) { /* fifo (named pipe) */ + self->sck = g_fifo_open(server); + //g_fifo_set_blocking(self->sck); + } + else { self->status = 0; + // MDBGLOG("trans","INFO\t[%s()]: done (1).",__func__); return 1; } if (error == -1) @@ -311,73 +555,272 @@ { if (g_tcp_can_send(self->sck, timeout)) { - self->status = 1; /* ok */ - self->type1 = 3; /* client */ - return 0; + self->status = 1; /* ok */ + self->type1 = 3; /* client */ + // MDBGLOG("trans","INFO\t[%s()]: done (2).",__func__); + return 0; } } + // MDBGLOG("trans","INFO\t[%s()]: done (3).",__func__); return 1; } self->status = 1; /* ok */ self->type1 = 3; /* client */ + + // MDBGLOG("trans","INFO\t[%s()]: done (4); error = %d.",__func__,error); + return 0; } /*****************************************************************************/ int APP_CC -trans_listen(struct trans* self, char* port) -{ - if (self->sck != 0) - { +trans_disconnect(struct trans * self) { + + // MDBGLOG("trans","INFO\t[%s()] called [%d, %d]",__func__,g_getpid(),g_gettid()); + + if (self == NULL) { + return -1; + } + + self->status = 0; /* not connected */ + self->type1 = 0; /* none */ + if (self->sck != 0 && (self->mode == 3 || self->mode == 0)) { + g_file_close(self->sck); + } + else if (self->sck != 0 && self->mode != 3) { g_tcp_close(self->sck); } - if (self->mode == 1) /* tcp */ + + return 0; +} + +/*****************************************************************************/ +int APP_CC +trans_attach(struct trans * self, int sck) { + + // MDBGLOG("trans","INFO\t[%s()]: called (sck = %d; self->mode = %d) [%d, %d]",__func__,sck,self->mode,g_getpid(),g_gettid()); + + if (self == NULL) { + // MDBGLOG("trans","ERROR\t[%s()]: invalid socket (sck = %d)",__func__,sck); + return -1; + } + + if (sck < 1) { + // MDBGLOG("trans","ERROR\t[%s()]: invalid socket (sck = %d)",__func__,sck); + return -1; + } + + if (self->sck != 0 && (self->mode == 3 || self->mode == 0)) { + g_file_close(self->sck); + } + else if (self->sck != 0) { + g_tcp_close(self->sck); + } + if (self->mode == 1 || self->mode == 2) /* tcp */ + { + self->sck = sck; + g_tcp_set_non_blocking(self->sck); + } + else if (self->mode == 3) /* fifo */ { + self->sck = sck; + //g_fifo_set_blocking(self->sck); + } + else if (self->mode == 0) /* stdio */ + { + self->sck = sck; + } + else { + self->status = 0; + // MDBGLOG("trans","ERROR\t[%s()]: unrecognized self->mode (%d)",__func__,self->mode); + return 1; + } + self->status = 1; /* ok */ + self->type1 = 3; /* client */ + + // MDBGLOG("trans","INFO\t[%s()]: done (self->status = %d; self->type1 = %d); error = %d.",__func__,self->status,self->type1); + + return 0; +} + +/*****************************************************************************/ +int APP_CC +trans_detach(struct trans * self) { + int rv = 0; + if (self == NULL) { + rv = -1; + } + else { + if (self->sck != 0 && (self->mode == 3 || self->mode == 0)) { + g_file_close(self->sck); + if (self->sck_out != 0) { + g_file_close(self->sck_out); + } + } + else if (self->sck != 0) { + g_tcp_close(self->sck); + } + self->sck = 0; + self->sck_out = 0; + self->status = 0; /* disconnected */ + self->type1 = 0; /* none */ + } + return rv; +} + +/*****************************************************************************/ +int APP_CC +trans_listen(struct trans* self, char* port) { + int rv = 0; + const int flags = AI_ADDRCONFIG | AI_PASSIVE; + + // MDBGLOG("trans","INFO\t[%s()]: called [%d, %d]",__func__,g_getpid(),g_gettid()); + + if (self == NULL) { + MDBGLOG("net","ERROR\t[%s()]: self is NULL",__func__); + rv = -1; + goto end; + } + if (self->sck != 0) { + g_tcp_close(self->sck); + } + if (self->mode == 1) { /* tcp */ self->sck = g_tcp_socket(); g_tcp_set_non_blocking(self->sck); - if (g_tcp_bind(self->sck, port) == 0) - { - if (g_tcp_listen(self->sck) == 0) - { - self->status = 1; /* ok */ - self->type1 = 1; /* listener */ - return 0; - } + if (g_tcp_bind_flags(self->sck, port, flags) == 0) { + if (g_tcp_listen(self->sck) == 0) { + self->status = 1; /* ok */ + self->type1 = 1; /* listener */ + rv = 0; + goto end; + } + else { + MDBGLOG("net","ERROR\t[%s()]: g_tcp_listen() failed",__func__); + rv = -1; + goto end; + } + } + else { + MDBGLOG("net","ERROR\t[%s()]: g_tcp_bind_flags() failed",__func__); + rv = -1; + goto end; } } else if (self->mode == 2) /* unix socket */ { g_free(self->listen_filename); - self->listen_filename = 0; + self->listen_filename = NULL; g_file_delete(port); self->sck = g_tcp_local_socket(); g_tcp_set_non_blocking(self->sck); - if (g_tcp_local_bind(self->sck, port) == 0) - { - self->listen_filename = g_strdup(port); - if (g_tcp_listen(self->sck) == 0) - { - g_chmod_hex(port, 0xffff); - self->status = 1; /* ok */ - self->type1 = 1; /* listener */ - return 0; - } - } + if (g_tcp_local_bind(self->sck, port) == 0) { + self->listen_filename = g_strdup(port); + if (g_tcp_listen(self->sck) == 0) + { + g_chmod_hex(port, 0xffff); + self->status = 1; /* ok */ + self->type1 = 1; /* listener */ + rv = 0; + goto end; + } + else { + MDBGLOG("net","ERROR\t[%s()]: g_tcp_listen() failed",__func__); + rv = -1; + goto end; + } + } + else { + MDBGLOG("net","ERROR\t[%s()]: g_tcp_local_bind() failed",__func__); + rv = -1; + goto end; + } + } + else { + MDBGLOG("net","ERROR\t[%s()]: unrecognized mode (self->mode = %d)",__func__,self->mode); + rv = -1; + goto end; } - return 1; + end:; + return rv; } /*****************************************************************************/ -struct stream* APP_CC -trans_get_in_s(struct trans* self) -{ - return self->in_s; +int APP_CC +trans_stop_listening(struct trans * self) { + int rv = 0; + if (self == NULL) { + rv = -1; + } + else { + if (self->sck != 0 && self->mode == 3) { + g_file_close(self->sck); + } + else if (self->sck != 0) { + g_tcp_close(self->sck); + } + self->sck = 0; + self->status = 0; /* disconnected */ + self->type1 = 0; /* none */ + } + return rv; } /*****************************************************************************/ struct stream* APP_CC -trans_get_out_s(struct trans* self, int size) -{ - init_stream(self->out_s, size); - return self->out_s; +trans_get_in_s(struct trans* self) { + struct stream * rv = (struct stream *)NULL; + // MDBGLOG("trans","INFO\t[%s()]: called [%d, %d]",__func__,g_getpid(),g_gettid()); + if (self == NULL) { + rv = (struct stream *)NULL; + } + else { + rv = self->in_s; + } + return rv; +} + +/*****************************************************************************/ +struct stream * APP_CC +trans_get_out_s(struct trans * self, size_t size) { + struct stream * rv = (struct stream *)NULL; + + // MDBGLOG("trans","INFO\t[%s()]: called [%d, %d]",__func__,g_getpid(),g_gettid()); + + if (self == NULL) { + rv = (struct stream *)NULL; + } + else { + init_stream(self->out_s, size); + rv = self->out_s; + } + return rv; +} + +/*****************************************************************************/ +ptrdiff_t APP_CC +trans_get_read_so_far(struct trans* self) { + ptrdiff_t rv = 0; + if (self == NULL) { + rv = -1; + } + else { + rv = self->in_s->end - self->in_s->data; + } + return rv; +} + +/*****************************************************************************/ +ptrdiff_t APP_CC +trans_get_written_so_far(struct trans* self) { + ptrdiff_t rv = 0; + if (self == NULL) { + rv = -1; + } + else if (self->out_s == NULL || self->out_s->data == NULL || self->out_s->end == NULL || self->out_s->end == self->out_s->data || self->out_s->p == NULL || self->out_s->p == self->out_s->data) { + rv = 0; + } + else { + rv = self->out_s->p - self->out_s->data; + } + return rv; } diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/common/trans.h posixrdp/posixxrdp.orig/common/trans.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/common/trans.h 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/common/trans.h 2010-11-08 09:56:43.000000000 +0100 @@ -26,49 +26,95 @@ #if !defined(TRANS_H) #define TRANS_H +#define __XRDP_TRANS_LOCKS__ +//#undef __XRDP_TRANS_LOCKS__ + +#include #include "arch.h" #include "parse.h" +#if defined(__XRDP_TRANS_LOCKS__) +#include "thread_calls.h" +#include "thread_macros.h" +#endif + struct trans; /* forward declaration */ -typedef int (*ttrans_data_in)(struct trans* self); +typedef size_t (*ttrans_data_in)(struct trans* self); typedef int (*ttrans_conn_in)(struct trans* self, struct trans* new_self); -struct trans -{ +typedef struct trans { tbus sck; - int mode; /* 1 tcp, 2 unix socket */ + tbus sck_out; + int mode; /* 1 = tcp, 2 = unix socket, 3 = FIFO */ int status; int type1; /* 1 listener 2 server 3 client */ + int ready; + int send_flags; + double rtime; ttrans_data_in trans_data_in; ttrans_conn_in trans_conn_in; - void* callback_data; + void * callback_data; int header_size; struct stream* in_s; struct stream* out_s; - char* listen_filename; -}; + tc_t * lock; + tc_t * listen_lock; + unsigned char locked; + unsigned char listening; + unsigned char running; + char * listen_filename; +} trans_t; struct trans* APP_CC -trans_create(int mode, int in_size, int out_size); +trans_create(int mode, size_t in_size, size_t out_size); void APP_CC trans_delete(struct trans* self); int APP_CC -trans_get_wait_objs(struct trans* self, tbus* objs, int* count, int* timeout); +trans_get_wait_objs(struct trans *, tbus [], ptrdiff_t *, int *); int APP_CC -trans_check_wait_objs(struct trans* self); +trans_check_wait_objs(struct trans *); +ptrdiff_t APP_CC +trans_force_read(struct trans *, size_t); +ptrdiff_t APP_CC +trans_read(struct trans *, size_t); +ptrdiff_t APP_CC +trans_force_write(struct trans* self); int APP_CC -trans_force_read(struct trans* self, int size); +trans_connect(struct trans *, const char *, const char *, int); int APP_CC -trans_force_write(struct trans* self); +trans_disconnect(struct trans *); +int APP_CC +trans_attach(struct trans * self, int sck); +int APP_CC +trans_detach(struct trans *); int APP_CC -trans_connect(struct trans* self, const char* server, const char* port, - int timeout); +trans_listen(struct trans *, char *); int APP_CC -trans_listen(struct trans* self, char* port); +trans_stop_listening(struct trans *); struct stream* APP_CC trans_get_in_s(struct trans* self); struct stream* APP_CC -trans_get_out_s(struct trans* self, int size); +trans_get_out_s(struct trans* self, size_t size); +ptrdiff_t APP_CC +trans_get_read_so_far(struct trans* self); +ptrdiff_t APP_CC +trans_get_written_so_far(struct trans* self); + + +#define LOCAL_STREAM_STRUCT(inx) inx ## _stream +#define LOCAL_STREAM_DATA(inx) inx ## _data +#define LOCAL_STREAM(inx) \ + char LOCAL_STREAM_DATA(inx)[MAX_STREAM]; \ + struct stream LOCAL_STREAM_STRUCT(inx); \ + struct stream * inx = &(LOCAL_STREAM_STRUCT(inx)); \ + { \ + g_memset(LOCAL_STREAM_DATA(inx),0x00,sizeof(LOCAL_STREAM_DATA(inx))); \ + g_memset(inx,0x00,sizeof(struct stream)); \ + inx->data = LOCAL_STREAM_DATA(inx); \ + inx->p = inx->data; \ + inx->end = inx->data; \ + inx->size = MAX_STREAM; \ + } #endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/configure.ac posixrdp/posixxrdp.orig/configure.ac --- xrdp/xrdp-0.5.0~20100303cvs.orig/configure.ac 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/configure.ac 2010-11-08 09:56:45.000000000 +0100 @@ -20,6 +20,36 @@ [pamuserpass=true], [pamuserpass=false]) AM_CONDITIONAL(SESMAN_PAMUSERPASS, [test x$pamuserpass = xtrue]) +AC_ARG_ENABLE(pulse, AS_HELP_STRING([--enable-pulse], + [Build with PulseAudio support (default: yes)]), + [pulse=true], [pulse=false]) + if test "${enable_pulse}" != "no" + then + PKG_CHECK_MODULES(PULSE, libpulse >= 0.9.11, + [ +# XRDP_ADD_PLUGIN([pulse]) +# XRDP_ADD_CFLAGS([pulse],[${PULSE_CFLAGS}]) +# XRDP_ADD_LDFLAGS([pulse],[${PULSE_LIBS}]) + ] + ) + fi +AM_CONDITIONAL(SESMAN_PULSE, [test x$pulse = xtrue]) + +AC_ARG_ENABLE(nl, AS_HELP_STRING([--enable-nl], + [Build with netlink support (default: yes)]), + [nl=true], [nl=false]) + if test "${enable_nl}" != "no" + then + PKG_CHECK_MODULES(NETLINK, libnl-1 >= 0.9.11, + [ +# XRDP_ADD_PLUGIN([nl]) +# XRDP_ADD_CFLAGS([nl],[${NETLINK_CFLAGS}]) +# XRDP_ADD_LDFLAGS([nl],[${NETLINK_LIBS}]) + ] + ) + fi +AM_CONDITIONAL(SESMAN_NETLINK, [test x$nl = xtrue]) + # checking for openssl AC_CHECK_HEADER([openssl/rc4.h], [], [AC_MSG_ERROR([please install libssl-dev or openssl-devel])], @@ -60,6 +90,7 @@ sesman/tools/Makefile sesman/sessvc/Makefile sesman/chansrv/Makefile + sesman/dynamic/Makefile keygen/Makefile docs/Makefile docs/man/Makefile diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/debian/changelog posixrdp/posixxrdp.orig/debian/changelog --- xrdp/xrdp-0.5.0~20100303cvs.orig/debian/changelog 2010-08-11 18:47:54.000000000 +0200 +++ posixrdp/posixxrdp.orig/debian/changelog 2010-11-08 10:35:26.000000000 +0100 @@ -1,3 +1,10 @@ +xrdp (0.5.0~20101104bzr-1) unstable; urgency=low + + * bzr branch lp:posixrdp + (http://bazaar.launchpad.net/~ryanaxp/posixrdp/devel/files) + + -- Arvid Requate Thu, 04 Nov 2010 10:18:15 +0100 + xrdp (0.5.0~20100303cvs-6) unstable; urgency=low * Add a patch to fix Alt-Gr issues with Windows TS client. diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/debian/patches/series posixrdp/posixxrdp.orig/debian/patches/series --- xrdp/xrdp-0.5.0~20100303cvs.orig/debian/patches/series 2010-08-11 18:47:54.000000000 +0200 +++ posixrdp/posixxrdp.orig/debian/patches/series 2010-11-08 10:35:26.000000000 +0100 @@ -3,3 +3,5 @@ 05-default-keymap.patch 06-xrdp_pidfile_early.patch alt-gr-fix.patch +sessionbroker.patch + diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/debian/patches/sessionbroker.patch posixrdp/posixxrdp.orig/debian/patches/sessionbroker.patch --- xrdp/xrdp-0.5.0~20100303cvs.orig/debian/patches/sessionbroker.patch 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/debian/patches/sessionbroker.patch 2010-11-08 10:35:26.000000000 +0100 @@ -0,0 +1,80 @@ +--- a/rdp/rdp.c ++++ b/rdp/rdp.c +@@ -21,6 +21,13 @@ + */ + + #include "rdp.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include + + /******************************************************************************/ + /* return error */ +@@ -43,6 +50,9 @@ + int DEFAULT_CC + lib_mod_connect(struct mod* mod) + { ++ FILE *fdpass; ++ char passpath[256]= "/tmp/"; ++ char command[512] = "/usr/sbin/univention-dvs-sessionbroker-xrdp"; + DEBUG(("in lib_mod_connect")); + /* clear screen */ + mod->server_begin_update(mod); +@@ -50,6 +60,21 @@ + mod->server_fill_rect(mod, 0, 0, mod->width, mod->height); + mod->server_end_update(mod); + /* connect */ ++ // hier reinhacken ++ strcat(passpath,mod->username); ++ fdpass = fopen(passpath,"w"); ++ fprintf(fdpass,"%s\n",mod->password); ++ fclose(fdpass); ++ //strcat(command,cmd); ++ strcat(command," -u "); ++ strcat(command,mod->username); ++ strcat(command," -y "); ++ strcat(command,passpath); ++ mod->pid = (pid_t*) malloc(sizeof(pid_t)); ++ mod->fdpipe = popen(command, "r"); ++ fscanf(mod->fdpipe,"%i\n",mod->pid); ++ fscanf(mod->fdpipe,"%s",mod->ip); ++ remove(passpath); + if (rdp_rdp_connect(mod->rdp_layer, mod->ip, mod->port) == 0) + { + mod->sck = mod->rdp_layer->sec_layer->mcs_layer->iso_layer->tcp_layer->sck; +@@ -326,6 +351,10 @@ + int EXPORT_CC + mod_exit(struct mod* mod) + { ++ kill(*(mod->pid),SIGUSR1); ++ free(mod->pid); ++ sleep(2); ++ pclose(mod->fdpipe); + DEBUG(("in mod_exit")); + g_free(mod); + DEBUG(("out mod_exit")); + +--- a/rdp/rdp.h ++++ b/rdp/rdp.h +@@ -27,6 +27,8 @@ + #include "ssl_calls.h" + #include "xrdp_constants.h" + #include "defines.h" ++#include ++#include + + struct rdp_brush + { +@@ -333,6 +335,8 @@ + char program[256]; + char directory[256]; + int keylayout; ++ FILE * fdpipe; ++ pid_t * pid; + int up_and_running; + struct stream* in_s; + tbus sck_obj; diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/debian/.pc/applied-patches posixrdp/posixxrdp.orig/debian/.pc/applied-patches --- xrdp/xrdp-0.5.0~20100303cvs.orig/debian/.pc/applied-patches 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/debian/.pc/applied-patches 2010-11-08 10:35:26.000000000 +0100 @@ -0,0 +1 @@ +01reuse-session.patch diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/debian/.pc/.version posixrdp/posixxrdp.orig/debian/.pc/.version --- xrdp/xrdp-0.5.0~20100303cvs.orig/debian/.pc/.version 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/debian/.pc/.version 2010-11-08 10:35:26.000000000 +0100 @@ -0,0 +1 @@ +2 diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/debian/rules posixrdp/posixxrdp.orig/debian/rules --- xrdp/xrdp-0.5.0~20100303cvs.orig/debian/rules 2010-08-11 18:47:54.000000000 +0200 +++ posixrdp/posixxrdp.orig/debian/rules 2010-11-08 10:35:26.000000000 +0100 @@ -5,8 +5,9 @@ dh $@ override_dh_auto_configure: + export PKG_CONFIG=/usr/bin/pkg-config ./bootstrap - ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var + ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --disable-pulse --disable-nl find -name Makefile | while read i; do sed -e 's#\(XRDP_PID_PATH.*/run\)#\1/xrdp#g' -i "$$i"; done override_dh_makeshlibs: @@ -21,7 +22,7 @@ # Clean up some files rm debian/xrdp/etc/xrdp/xrdp.sh rm debian/xrdp/usr/lib/xrdp/*a - rm debian/xrdp/usr/bin/xrdp-sestest + #rm debian/xrdp/usr/bin/xrdp-sestest # Use our own startwm.sh install -m 755 debian/startwm.sh debian/xrdp/etc/xrdp # Move rsakeys to documentation diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/design.txt posixrdp/posixxrdp.orig/design.txt --- xrdp/xrdp-0.5.0~20100303cvs.orig/design.txt 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/design.txt 2010-11-08 09:56:45.000000000 +0100 @@ -7,7 +7,7 @@ one could be running a X11 session clients control the screen size and color depth -all controlled by a cofiguaration file. +all controlled by a configuration file. you can create a lib or use a lib with your executable that talks to xrdp server. diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/docs/ckill.sh posixrdp/posixxrdp.orig/docs/ckill.sh --- xrdp/xrdp-0.5.0~20100303cvs.orig/docs/ckill.sh 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/docs/ckill.sh 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,18 @@ +#!/bin/sh +# ps aux | grep X ; ps aux | grep rdp ; ps aux | grep ssh-agent + +invoke-rc.d xrdp stop +unset TMPARGS +TMP=$(ps -C Xvnc,X11rdp,xrdp,xrdp-sesman,xrdp-chansrv,xrdp-sessvc,startwm.sh,ssh-agent,xrdp-sesadmin,xrdp-sesrun,xrdp_drdynvc_interface,xrdp_rdpeai -o pid) +for f in ${TMP} +do + if [ "${f}" != "PID" ]; then +TMPARGS=${TMPARGS}" ${f}" + fi +done +/bin/kill -s KILL ${TMPARGS} &>0 +rm /tmp/xrdp_* &>0 +rm -r /tmp/.X1* &>0 +rm /var/run/xrdp*pid &>0 + + diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/keygen/Makefile.am posixrdp/posixxrdp.orig/keygen/Makefile.am --- xrdp/xrdp-0.5.0~20100303cvs.orig/keygen/Makefile.am 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/keygen/Makefile.am 2010-11-08 09:56:45.000000000 +0100 @@ -1,9 +1,17 @@ AM_CFLAGS = \ + -pthread \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ -DXRDP_SBIN_PATH=\"${sbindir}\" \ -DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \ - -DXRDP_PID_PATH=\"${localstatedir}/run\" + -DXRDP_PID_PATH=\"${localstatedir}/run\" \ + -D_FILE_OFFSET_BITS=64 \ + -D_REENTRANT \ + -D_GNU_SOURCE \ + -D_XOPEN_SOURCE_EXTENDED + +AM_LDFLAGS = \ + -lpthread INCLUDES = \ -I$(top_srcdir)/common @@ -14,4 +22,4 @@ xrdp_keygen_SOURCES = keygen.c xrdp_keygen_LDADD = \ - $(top_srcdir)/common/libcommon.la + $(top_builddir)/common/libcommon.la diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/libxrdp/libxrdp.c posixrdp/posixxrdp.orig/libxrdp/libxrdp.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/libxrdp/libxrdp.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/libxrdp/libxrdp.c 2010-11-08 09:56:44.000000000 +0100 @@ -133,9 +133,9 @@ int EXPORT_CC libxrdp_send_palette(struct xrdp_session* session, int* palette) { - int i; - int color; - struct stream* s; + int i = 0; + int color = 0; + struct stream* s = (struct stream *)NULL; if (session->client_info->bpp > 8) { @@ -173,24 +173,25 @@ libxrdp_send_bitmap(struct xrdp_session* session, int width, int height, int bpp, char* data, int x, int y, int cx, int cy) { - int line_size; - int i; - int j; - int total_lines; - int lines_sending; - int Bpp; - int e; - int bufsize; - int total_bufsize; - int num_updates; - char* p_num_updates; - char* p; - char* q; - struct stream* s; - struct stream* temp_s; + int data_size = 0; + int line_size = 0; + int i = 0; + int j = 0; + int total_lines = 0; + int lines_sending = 0; + int Bpp = 0; + int e = 0; + int bufsize = 0; + int total_bufsize = 0; + int num_updates = 0; + char* p_num_updates = (char *)NULL; + char* p = (char *)NULL; + char* q = (char *)NULL; + struct stream* s = (struct stream *)NULL; + struct stream* temp_s = (struct stream *)NULL; DEBUG(("libxrdp_send_bitmap sending bitmap")); - Bpp = (bpp + 7) / 8; + Bpp = (bpp == 32) ? 3 : (bpp + 7) / 8; e = width % 4; if (e != 0) { @@ -290,6 +291,8 @@ } else { + lines_sending = 0; + data_size = width * height * Bpp; total_lines = height; i = 0; p = data; @@ -621,10 +624,10 @@ libxrdp_query_channel(struct xrdp_session* session, int index, char* channel_name, int* channel_flags) { - int count; - struct xrdp_rdp* rdp; - struct xrdp_mcs* mcs; - struct mcs_channel_item* channel_item; + int count = 0; + struct xrdp_rdp* rdp = (struct xrdp_rdp *)NULL; + struct xrdp_mcs* mcs = (struct xrdp_mcs *)NULL; + struct mcs_channel_item* channel_item = (struct mcs_channel_item *)NULL; rdp = (struct xrdp_rdp*)session->rdp; mcs = rdp->sec_layer->mcs_layer; @@ -657,11 +660,11 @@ int EXPORT_CC libxrdp_get_channel_id(struct xrdp_session* session, char* name) { - int index; - int count; - struct xrdp_rdp* rdp; - struct xrdp_mcs* mcs; - struct mcs_channel_item* channel_item; + int index = 0; + int count = 0; + struct xrdp_rdp* rdp = NULL; + struct xrdp_mcs* mcs = NULL; + struct mcs_channel_item* channel_item = NULL; rdp = (struct xrdp_rdp*)session->rdp; mcs = rdp->sec_layer->mcs_layer; @@ -687,10 +690,10 @@ char* data, int data_len, int total_data_len, int flags) { - struct xrdp_rdp* rdp; - struct xrdp_sec* sec; - struct xrdp_channel* chan; - struct stream* s; + struct xrdp_rdp* rdp = NULL; + struct xrdp_sec* sec = NULL; + struct xrdp_channel* chan = NULL; + struct stream* s = NULL; rdp = (struct xrdp_rdp*)session->rdp; sec = rdp->sec_layer; diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/libxrdp/libxrdpinc.h posixrdp/posixxrdp.orig/libxrdp/libxrdpinc.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/libxrdp/libxrdpinc.h 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/libxrdp/libxrdpinc.h 2010-11-08 09:56:44.000000000 +0100 @@ -20,14 +20,119 @@ */ -#if !defined(LIBXRDPINC_H) +#ifndef LIBXRDPINC_H #define LIBXRDPINC_H +#include +#include +#include +#include +#include + +#define RNS_UD_COLOR_4BPP 0xca00 +#define RNS_UD_COLOR_8BPP 0xca01 + +#define RNS_UD_24BPP_SUPPORT 0x0001 +#define RNS_UD_16BPP_SUPPORT 0x0002 +#define RNS_UD_15BPP_SUPPORT 0x0004 +#define RNS_UD_32BPP_SUPPORT 0x0008 + +#define RNS_UD_CS_SUPPORT_ERRINFO_PDU 0x0001 +#define RNS_UD_CS_WANT_32BPP_SESSION 0x0002 +#define RNS_UD_CS_SUPPORT_STATUSINFO_PDU 0x0004 +#define RNS_UD_CS_STRONG_ASYMMETRIC_KEYS 0x0008 +#define RNS_UD_CS_VALID_CONNECTION_TYPE 0x0020 +#define RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU 0x0040 + +#define CONNECTION_TYPE_MODEM 1 +#define CONNECTION_TYPE_BROADBAND_LOW 2 +#define CONNECTION_TYPE_SATELLITE 3 +#define CONNECTION_TYPE_BROADBAND_HIGH 4 +#define CONNECTION_TYPE_WAN 5 +#define CONNECTION_TYPE_LAN 6 + +/* Constants used in the TS_INFO_PACKET structure */ +#define INFO_MOUSE 0x00000001 +#define INFO_DISABLECTRLALTDEL 0x00000002 +#define INFO_AUTOLOGON 0x00000008 +#define INFO_UNICODE 0x00000010 +#define INFO_MAXIMIZESHELL 0x00000020 +#define INFO_LOGONNOTIFY 0x00000040 +#define INFO_COMPRESSION 0x00000080 +#define CompressionTypeMask 0x00001E00 +#define PACKET_COMPR_TYPE_8K 0 +#define PACKET_COMPR_TYPE_64K 1 +#define PACKET_COMPR_TYPE_RDP6 2 +#define PACKET_COMPR_TYPE_RDP61 3 +#define INFO_ENABLEWINDOWSKEY 0x00000100 +#define INFO_REMOTECONSOLEAUDIO 0x00002000 +#define INFO_FORCE_ENCRYPTED_CS_PDU 0x00004000 +#define INFO_RAIL 0x00008000 +#define INFO_LOGONERRORS 0x00010000 +#define INFO_MOUSE_HAS_WHEEL 0x00020000 +#define INFO_PASSWORD_IS_SC_PIN 0x00040000 +#define INFO_NOAUDIOPLAYBACK 0x00080000 +#define INFO_USING_SAVED_CREDS 0x00100000 + +/* bit flags in the "performanceFlags" field */ +#define PERF_DISABLE_WALLPAPER 0x00000001 +#define PERF_DISABLE_FULLWINDOWDRAG 0x00000002 +#define PERF_DISABLE_MENUANIMATIONS 0x00000004 +#define PERF_DISABLE_THEMING 0x00000008 +#define PERF_RESERVED1 0x00000010 +#define PERF_DISABLE_CURSOR_SHADOW 0x00000020 +#define PERF_DISABLE_CURSORSETTINGS 0x00000040 +#define PERF_ENABLE_FONT_SMOOTHING 0x00000080 +#define PERF_ENABLE_DESKTOP_COMPOSITION 0x00000100 +#define PERF_RESERVED2 0x80000000 + +#define CI_AF_INET 0x0002 +#define CI_AF_INET6 0x0017 + +/* TS_GENERAL_CAPABILITYSET */ +#define OSMAJORTYPE_UNSPECIFIED 0x0000 +#define OSMAJORTYPE_WINDOWS 0x0001 +#define OSMAJORTYPE_OS2 0x0002 +#define OSMAJORTYPE_MACINTOSH 0x0003 +#define OSMAJORTYPE_UNIX 0x0004 +#define OSMINORTYPE_UNSPECIFIED 0x0000 +#define OSMINORTYPE_WINDOWS_31X 0x0001 +#define TS_OSMINORTYPE_WINDOWS_95 0x0002 +#define TS_OSMINORTYPE_WINDOWS_NT 0x0003 +#define TS_OSMINORTYPE_OS2_V21 0x0004 +#define TS_OSMINORTYPE_POWER_PC 0x0005 +#define TS_OSMINORTYPE_MACINTOSH 0x0006 +#define TS_OSMINORTYPE_NATIVE_XSERVER 0x0007 +#define TS_OSMINORTYPE_PSEUDO_XSERVER 0x0008 + +#define DRAW_ALLOW_DYNAMIC_COLOR_FIDELITY 0x02 +#define DRAW_ALLOW_COLOR_SUBSAMPLING 0x04 +#define DRAW_ALLOW_SKIP_ALPHA 0x08 + + struct xrdp_client_info { int bpp; int width; int height; + uint32_t version; + uint16_t colorDepth; + uint16_t postBeta2ColorDepth; + uint16_t highColorDepth; + uint16_t supportedColorDepths; + uint16_t earlyCapabilityFlags; + uint32_t keyboardLayout; + uint32_t keyboardType; + uint32_t keyboardSubType; + uint32_t keyboardFunctionKey; + uint16_t imeFileName[32]; + uint32_t serialNumber; + uint32_t clientBuild; + uint16_t clientName[16]; + uint16_t clientProductId; + uint8_t clientDigProductId[64]; + uint8_t connectionType; + uint32_t serverSelectedProtocol; /* bitmap cache info */ int cache1_entries; int cache1_size; @@ -60,9 +165,22 @@ int channel_code; /* 0 = no channels 1 = channels */ int sound_code; /* 1 = leave sound at server */ int is_mce; - int rdp5_performanceflags; + uint32_t rdp5_performanceflags; int brush_cache_code; /* 0 = no cache 1 = 8x8 standard cache 2 = arbitrary dimensions */ + uint32_t flags; /* from the TS_INFO_PACKET structure (see MS-RDPBCGR.pdf, v20091104, at section 2.2.1.11.1.1, page 58 et seq. */ + + /* TS_EXTENDED_INFO_PACKET */ + uint32_t CodePage; + uint16_t clientAddressFamily; /* 0x0002 = AF_INET; 0x0017 = AF_INET6 */ + uint16_t cbClientAddress; /* size in bytes of the data in the "clientAddress" field (including the length of the required NULL terminator) */ + uint8_t * clientAddress; + uint16_t cbClientDir; + uint8_t * clientDir; + uint8_t clientTimeZone[172]; /* TS_TIME_ZONE_INFORMATION */ + uint16_t cbAutoReconnectLen; + uint8_t autoReconnectCookie[28]; /* ARC_CS_PRIVATE_PACKET */ + uint32_t clientSessionId; }; struct xrdp_brush @@ -215,4 +333,10 @@ int width, int height, int bpp, int type, int size, char* data, int cache_id); +/* Unicode junk */ +typedef uint16_t UTF16; +typedef uint32_t UTF32; +UTF32 utf16_to_utf32(UTF16, UTF16); +UTF16 * utf32_to_utf16(UTF32); + #endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/libxrdp/Makefile.am posixrdp/posixxrdp.orig/libxrdp/Makefile.am --- xrdp/xrdp-0.5.0~20100303cvs.orig/libxrdp/Makefile.am 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/libxrdp/Makefile.am 2010-11-08 09:56:44.000000000 +0100 @@ -1,9 +1,17 @@ AM_CFLAGS = \ + -pthread \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ -DXRDP_SBIN_PATH=\"${sbindir}\" \ -DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \ - -DXRDP_PID_PATH=\"${localstatedir}/run\" + -DXRDP_PID_PATH=\"${localstatedir}/run\" \ + -D_FILE_OFFSET_BITS=64 \ + -D_REENTRANT \ + -D_GNU_SOURCE \ + -D_XOPEN_SOURCE_EXTENDED + +AM_LDFLAGS = \ + -lpthread INCLUDES = \ -I$(top_srcdir)/common @@ -23,4 +31,4 @@ xrdp_bitmap_compress.c libxrdp_la_LIBADD = \ - $(top_srcdir)/common/libcommon.la + $(top_builddir)/common/libcommon.la diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/libxrdp/xrdp_bitmap_compress.c posixrdp/posixxrdp.orig/libxrdp/xrdp_bitmap_compress.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/libxrdp/xrdp_bitmap_compress.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/libxrdp/xrdp_bitmap_compress.c 2010-11-08 09:56:44.000000000 +0100 @@ -950,7 +950,7 @@ } else if ((bpp == 15) || (bpp == 16)) { - mix = 0xffff; + mix = (bpp == 15) ? 0xba1f : 0xffff; out_count = end * 2; line = in_data + width * start_line * 2; while (start_line >= 0 && out_count < 32768) @@ -1470,5 +1470,268 @@ OUT_COPY_COUNT3(count, s, temp_s); } } + else if (bpp == 32) + { + mix = 0xffffff; + out_count = end * 4; + line = in_data + width * start_line * 4; + while (start_line >= 0 && out_count < 32768) + { + i = (s->p - s->data) + count * 4; + if (i - (color_count * 3) >= byte_limit && + i - (bicolor_count * 3) >= byte_limit && + i - (fill_count * 3) >= byte_limit && + i - (mix_count * 3) >= byte_limit && + i - (fom_count * 3) >= byte_limit) + { + break; + } + out_count += end * 4; + for (i = 0; i < end; i++) + { + /* read next pixel */ + IN_PIXEL32(line, i, 0, width, last_pixel, pixel); + IN_PIXEL32(last_line, i, 0, width, last_ypixel, ypixel); + if (!TEST_FILL) + { + if (fill_count > 3 && + fill_count >= color_count && + fill_count >= bicolor_count && + fill_count >= mix_count && + fill_count >= fom_count) + { + count -= fill_count; + OUT_COPY_COUNT3(count, s, temp_s); + OUT_FILL_COUNT3(fill_count, s); + RESET_COUNTS; + } + fill_count = 0; + } + if (!TEST_MIX) + { + if (mix_count > 3 && + mix_count >= fill_count && + mix_count >= bicolor_count && + mix_count >= color_count && + mix_count >= fom_count) + { + count -= mix_count; + OUT_COPY_COUNT3(count, s, temp_s); + OUT_MIX_COUNT3(mix_count, s); + RESET_COUNTS; + } + mix_count = 0; + } + if (!TEST_COLOR) + { + if (color_count > 3 && + color_count >= fill_count && + color_count >= bicolor_count && + color_count >= mix_count && + color_count >= fom_count) + { + count -= color_count; + OUT_COPY_COUNT3(count, s, temp_s); + OUT_COLOR_COUNT3(color_count, s, last_pixel); + RESET_COUNTS; + } + color_count = 0; + } + if (!TEST_BICOLOR) + { + if (bicolor_count > 3 && + bicolor_count >= fill_count && + bicolor_count >= color_count && + bicolor_count >= mix_count && + bicolor_count >= fom_count) + { + if ((bicolor_count % 2) == 0) + { + count -= bicolor_count; + OUT_COPY_COUNT3(count, s, temp_s); + OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor1, bicolor2); + } + else + { + bicolor_count--; + count -= bicolor_count; + OUT_COPY_COUNT3(count, s, temp_s); + OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor2, bicolor1); + } + RESET_COUNTS; + } + bicolor_count = 0; + bicolor1 = last_pixel; + bicolor2 = pixel; + bicolor_spin = 0; + } + if (!TEST_FOM) + { + if (fom_count > 3 && + fom_count >= fill_count && + fom_count >= color_count && + fom_count >= mix_count && + fom_count >= bicolor_count) + { + count -= fom_count; + OUT_COPY_COUNT3(count, s, temp_s); + OUT_FOM_COUNT3(fom_count, s, fom_mask, fom_mask_len); + RESET_COUNTS; + } + fom_count = 0; + fom_mask_len = 0; + } + if (TEST_FILL) + { + fill_count++; + } + if (TEST_MIX) + { + mix_count++; + } + if (TEST_COLOR) + { + color_count++; + } + if (TEST_BICOLOR) + { + bicolor_spin = !bicolor_spin; + bicolor_count++; + } + if (TEST_FOM) + { + if ((fom_count % 8) == 0) + { + fom_mask[fom_mask_len] = 0; + fom_mask_len++; + } + if (pixel == (ypixel ^ mix)) + { + fom_mask[fom_mask_len - 1] |= (1 << (fom_count % 8)); + } + fom_count++; + } + out_uint8(temp_s, 0x00); + out_uint8(temp_s, pixel & 0xff); + out_uint8(temp_s, (pixel >> 8) & 0xff); + out_uint8(temp_s, (pixel >> 16) & 0xff); + count++; + last_pixel = pixel; + last_ypixel = ypixel; + } + /* can't take fix, mix, or fom past first line */ + if (last_line == 0) + { + if (fill_count > 3 && + fill_count >= color_count && + fill_count >= bicolor_count && + fill_count >= mix_count && + fill_count >= fom_count) + { + count -= fill_count; + OUT_COPY_COUNT3(count, s, temp_s); + OUT_FILL_COUNT3(fill_count, s); + RESET_COUNTS; + } + fill_count = 0; + if (mix_count > 3 && + mix_count >= fill_count && + mix_count >= bicolor_count && + mix_count >= color_count && + mix_count >= fom_count) + { + count -= mix_count; + OUT_COPY_COUNT3(count, s, temp_s); + OUT_MIX_COUNT3(mix_count, s); + RESET_COUNTS; + } + mix_count = 0; + if (fom_count > 3 && + fom_count >= fill_count && + fom_count >= color_count && + fom_count >= mix_count && + fom_count >= bicolor_count) + { + count -= fom_count; + OUT_COPY_COUNT3(count, s, temp_s); + OUT_FOM_COUNT3(fom_count, s, fom_mask, fom_mask_len); + RESET_COUNTS; + } + fom_count = 0; + fom_mask_len = 0; + } + last_line = line; + line = line - width * 4; + start_line--; + lines_sent++; + } + if (fill_count > 3 && + fill_count >= color_count && + fill_count >= bicolor_count && + fill_count >= mix_count && + fill_count >= fom_count) + { + count -= fill_count; + OUT_COPY_COUNT3(count, s, temp_s); + OUT_FILL_COUNT3(fill_count, s); + } + else if (mix_count > 3 && + mix_count >= color_count && + mix_count >= bicolor_count && + mix_count >= fill_count && + mix_count >= fom_count) + { + count -= mix_count; + OUT_COPY_COUNT3(count, s, temp_s); + OUT_MIX_COUNT3(mix_count, s); + } + else if (color_count > 3 && + color_count >= mix_count && + color_count >= bicolor_count && + color_count >= fill_count && + color_count >= fom_count) + { + count -= color_count; + OUT_COPY_COUNT3(count, s, temp_s); + OUT_COLOR_COUNT3(color_count, s, last_pixel); + } + else if (bicolor_count > 3 && + bicolor_count >= mix_count && + bicolor_count >= color_count && + bicolor_count >= fill_count && + bicolor_count >= fom_count) + { + if ((bicolor_count % 2) == 0) + { + count -= bicolor_count; + OUT_COPY_COUNT3(count, s, temp_s); + OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor1, bicolor2); + } + else + { + bicolor_count--; + count -= bicolor_count; + OUT_COPY_COUNT3(count, s, temp_s); + OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor2, bicolor1); + } + count -= bicolor_count; + OUT_COPY_COUNT3(count, s, temp_s); + OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor1, bicolor2); + } + else if (fom_count > 3 && + fom_count >= mix_count && + fom_count >= color_count && + fom_count >= fill_count && + fom_count >= bicolor_count) + { + count -= fom_count; + OUT_COPY_COUNT3(count, s, temp_s); + OUT_FOM_COUNT3(fom_count, s, fom_mask, fom_mask_len); + } + else + { + OUT_COPY_COUNT3(count, s, temp_s); + } + } return lines_sent; } diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/libxrdp/xrdp_channel.c posixrdp/posixxrdp.orig/libxrdp/xrdp_channel.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/libxrdp/xrdp_channel.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/libxrdp/xrdp_channel.c 2010-11-08 09:56:44.000000000 +0100 @@ -170,6 +170,7 @@ g_writeln("xrdp_channel_process, channel not found"); return 1; } + rv = 0; in_uint32_le(s, length); in_uint32_le(s, flags); rv = xrdp_channel_call_callback(self, s, channel_id, length, flags); diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/libxrdp/xrdp_orders.c posixrdp/posixxrdp.orig/libxrdp/xrdp_orders.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/libxrdp/xrdp_orders.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/libxrdp/xrdp_orders.c 2010-11-08 09:56:44.000000000 +0100 @@ -336,10 +336,10 @@ char* present_ptr, int present, int present_size) { - int move_up_count; - int index; - int size; - int keep_looking; + int move_up_count = 0; + int index = 0; + int size = 0; + int keep_looking = 1; move_up_count = 0; keep_looking = 1; @@ -527,11 +527,11 @@ int cx, int cy, int srcx, int srcy, int rop, struct xrdp_rect* rect) { - int order_flags; - int vals[12]; - int present; - char* present_ptr; - char* order_flags_ptr; + int order_flags = 0; + int vals[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int present = 0; + char* present_ptr = (char *)NULL; + char* order_flags_ptr = (char *)NULL; xrdp_orders_check(self, 25); self->order_count++; @@ -996,13 +996,15 @@ struct xrdp_pen* pen, struct xrdp_rect* rect) { - int order_flags; - int vals[8]; - int present; - char* present_ptr; - char* order_flags_ptr; + int order_flags = 0; + int vals[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + int present = 0; + char* present_ptr = (char *)NULL; + char* order_flags_ptr = (char *)NULL; struct xrdp_pen blank_pen; + g_memset(&blank_pen,0,sizeof(struct xrdp_pen)); + /* if mix mode or rop are out of range, mstsc build 6000+ will parse the orders wrong */ if ((mix_mode < 1) || (mix_mode > 2)) /* TRANSPARENT(1) or OPAQUE(2) */ @@ -1176,11 +1178,11 @@ int rop, int srcx, int srcy, int cache_idx, struct xrdp_rect* rect) { - int order_flags; - int vals[12]; - int present; - char* present_ptr; - char* order_flags_ptr; + int order_flags = 0; + int vals[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int present = 0; + char* present_ptr = (char *)NULL; + char* order_flags_ptr = (char *)NULL; xrdp_orders_check(self, 30); self->order_count++; @@ -1352,10 +1354,10 @@ int x, int y, char* data, int data_len, struct xrdp_rect* rect) { - int order_flags; - int present; - char* present_ptr; - char* order_flags_ptr; + int order_flags = 0; + int present = 0; + char* present_ptr = (char *)NULL; + char* order_flags_ptr = (char *)NULL; xrdp_orders_check(self, 100); self->order_count++; @@ -1546,14 +1548,14 @@ int width, int height, int bpp, char* data, int cache_id, int cache_idx) { - int order_flags; - int len; - int bufsize; - int Bpp; - int i; - int j; - int pixel; - int e; + int order_flags = 0; + int len = 0; + int bufsize = 0; + int Bpp = 0; + int i = 0; + int j = 0; + int pixel = 0; + int e = 0; if (width > 64) { @@ -1570,7 +1572,7 @@ { e = 4 - e; } - Bpp = (bpp + 7) / 8; + Bpp = (bpp == 32) ? 3 : (bpp + 7) / 8; bufsize = (width + e) * height * Bpp; xrdp_orders_check(self, bufsize + 16); self->order_count++; @@ -1591,7 +1593,7 @@ { for (j = 0; j < width; j++) { - if (Bpp == 3) + if ((Bpp == 3) || (Bpp == 4)) { pixel = GETPIXEL32(data, j, i, width); out_uint8(self->out_s, pixel >> 16); @@ -1626,16 +1628,16 @@ int width, int height, int bpp, char* data, int cache_id, int cache_idx) { - int order_flags; - int len; - int bufsize; - int Bpp; - int i; - int lines_sending; - int e; - struct stream* s; - struct stream* temp_s; - char* p; + int order_flags = 0; + int len = 0; + int bufsize = 0; + int Bpp = 0; + int i = 0; + int lines_sending = 0; + int e = 0; + struct stream* s = NULL; + struct stream* temp_s = NULL; + char* p = NULL; if (width > 64) { @@ -1669,7 +1671,7 @@ return 1; } bufsize = (int)(s->p - p); - Bpp = (bpp + 7) / 8; + Bpp = (bpp == 32) ? 3 : (bpp + 7) / 8; xrdp_orders_check(self, bufsize + 16); self->order_count++; order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY; @@ -1717,9 +1719,9 @@ struct xrdp_font_char* font_char, int font_index, int char_index) { - int order_flags; - int datasize; - int len; + int order_flags = 0; + int datasize = 0; + int len = 0; datasize = FONT_DATASIZE(font_char); xrdp_orders_check(self, datasize + 18); @@ -1749,14 +1751,14 @@ int width, int height, int bpp, char* data, int cache_id, int cache_idx) { - int order_flags; - int len; - int bufsize; - int Bpp; - int i; - int j; - int pixel; - int e; + int order_flags = 0; + int len = 0; + int bufsize = 0; + int Bpp = 0; + int i = 0; + int j = 0; + int pixel = 0; + int e = 0; if (width > 64) { @@ -1773,7 +1775,7 @@ { e = 4 - e; } - Bpp = (bpp + 7) / 8; + Bpp = (bpp == 32) ? 3 : (bpp + 7) / 8; bufsize = (width + e) * height * Bpp; xrdp_orders_check(self, bufsize + 14); self->order_count++; @@ -1795,7 +1797,15 @@ { for (j = 0; j < width; j++) { - if (Bpp == 3) + if (Bpp == 4) + { + pixel = GETPIXEL32(data, j, i, width); + out_uint8(self->out_s, pixel >> 24); + out_uint8(self->out_s, pixel >> 16); + out_uint8(self->out_s, pixel >> 8); + out_uint8(self->out_s, pixel); + } + else if (Bpp == 3) { pixel = GETPIXEL32(data, j, i, width); out_uint8(self->out_s, pixel >> 16); @@ -1830,16 +1840,16 @@ int width, int height, int bpp, char* data, int cache_id, int cache_idx) { - int order_flags; - int len; - int bufsize; - int Bpp; - int i; - int lines_sending; - int e; - struct stream* s; - struct stream* temp_s; - char* p; + int order_flags = 0; + int len = 0; + int bufsize = 0; + int Bpp = 0; + int i = 0; + int lines_sending = 0; + int e = 0; + struct stream* s = NULL; + struct stream* temp_s = NULL; + char* p = NULL; if (width > 64) { @@ -1873,7 +1883,7 @@ return 1; } bufsize = (int)(s->p - p); - Bpp = (bpp + 7) / 8; + Bpp = (bpp == 32) ? 3 : (bpp + 7) / 8; xrdp_orders_check(self, bufsize + 14); self->order_count++; order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY; @@ -1904,8 +1914,8 @@ xrdp_orders_send_brush(struct xrdp_orders* self, int width, int height, int bpp, int type, int size, char* data, int cache_id) { - int order_flags; - int len; + int order_flags = 0; + int len = 0; xrdp_orders_check(self, size + 12); self->order_count++; diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/libxrdp/xrdp_rdp.c posixrdp/posixxrdp.orig/libxrdp/xrdp_rdp.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/libxrdp/xrdp_rdp.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/libxrdp/xrdp_rdp.c 2010-11-08 09:56:44.000000000 +0100 @@ -20,7 +20,13 @@ */ +#include +#ifdef _XRDP_ENABLE_I18N_ +#include +#include +#endif #include "libxrdp.h" +#include "dbg.h" /* some compilers need unsigned char to avoid warnings */ static tui8 g_unknown1[172] = @@ -57,13 +63,16 @@ static int APP_CC xrdp_rdp_read_config(struct xrdp_client_info* client_info) { - int index; - struct list* items; - struct list* values; - char* item; - char* value; + int index = 0; + struct list* items = (struct list *)NULL; + struct list* values = (struct list *)NULL; + char* item = (char *)NULL; + char* value = (char *)NULL; char cfg_file[256]; + /* initialize (zero out) local variables: */ + g_memset(cfg_file,0,sizeof(char) * 256); + items = list_create(); items->auto_free = 1; values = list_create(); @@ -124,7 +133,7 @@ struct xrdp_rdp* APP_CC xrdp_rdp_create(struct xrdp_session* session, int sck) { - struct xrdp_rdp* self; + struct xrdp_rdp* self = (struct xrdp_rdp *)NULL; DEBUG(("in xrdp_rdp_create")); self = (struct xrdp_rdp*)g_malloc(sizeof(struct xrdp_rdp), 1); @@ -187,10 +196,10 @@ int APP_CC xrdp_rdp_recv(struct xrdp_rdp* self, struct stream* s, int* code) { - int error; - int len; - int pdu_code; - int chan; + int error = 0; + int len = 0; + int pdu_code = 0; + int chan = 0; DEBUG(("in xrdp_rdp_recv")); if (s->next_packet == 0 || s->next_packet >= s->end) @@ -226,16 +235,14 @@ { s->p = s->next_packet; } - if (!s_check_rem(s, 6)) + in_uint16_le(s, len); + if (len == 0x8000) { - s->next_packet = 0; + s->next_packet += 8; *code = 0; DEBUG(("out xrdp_rdp_recv")); - len = (int)(s->end - s->p); - g_writeln("xrdp_rdp_recv: bad RDP packet, length [%d]", len); return 0; } - in_uint16_le(s, len); in_uint16_le(s, pdu_code); *code = pdu_code & 0xf; in_uint8s(s, 2); /* mcs user id */ @@ -248,7 +255,7 @@ int APP_CC xrdp_rdp_send(struct xrdp_rdp* self, struct stream* s, int pdu_type) { - int len; + int len = 0; DEBUG(("in xrdp_rdp_send")); s_pop_layer(s, rdp_hdr); @@ -270,7 +277,7 @@ xrdp_rdp_send_data(struct xrdp_rdp* self, struct stream* s, int data_pdu_type) { - int len; + int len = 0; DEBUG(("in xrdp_rdp_send_data")); s_pop_layer(s, rdp_hdr); @@ -298,7 +305,7 @@ int APP_CC xrdp_rdp_send_data_update_sync(struct xrdp_rdp* self) { - struct stream* s; + struct stream * s = (struct stream *)NULL; make_stream(s); init_stream(s, 8192); @@ -327,25 +334,100 @@ static int APP_CC xrdp_rdp_parse_client_mcs_data(struct xrdp_rdp* self) { - struct stream* p; - int i; + struct stream* p = (struct stream *)NULL; + int i = 0; + char str1[16]; + char str2[32]; + wint_t wstr1[16]; + wint_t wstr2[32]; + uint8_t hi = 0x0000; + uint8_t lo = 0x0000; + uint16_t ud_length = 0x0000; + uint16_t ud_type = 0x0000; + + MDBGLOG("sound","INFO\t[%s()]: !!!! xrdp_rdp_parse_client_mcs_data() called !!!! ",__func__); + + self->client_info.version = 0x00000000; + self->client_info.colorDepth = 0x0000; + self->client_info.highColorDepth = 0x0000; + self->client_info.postBeta2ColorDepth = 0x0000; + self->client_info.earlyCapabilityFlags = 0x0000; + self->client_info.supportedColorDepths = 0x0000; + self->client_info.keyboardLayout = 0x00000000; + self->client_info.keyboardType = 0x00000000; + self->client_info.keyboardSubType = 0x00000000; + self->client_info.keyboardFunctionKey = 0x00000000; + self->client_info.clientBuild = 0x00000000; + self->client_info.clientProductId = 0x0000; + self->client_info.connectionType = 0x00; + self->client_info.serialNumber = 0x00000000; + self->client_info.serverSelectedProtocol = 0x00000000; + memset((void *)(self->client_info.clientName),(int)0x0000,(size_t)(sizeof(uint16_t) * 16)); + memset((void *)(self->client_info.imeFileName),(int)0x00000000,(size_t)(sizeof(uint16_t) * 32)); + memset((void *)(self->client_info.clientDigProductId),(int)0x00,(size_t)(sizeof(uint8_t) * 64)); + memset(str1,0,sizeof(char) * 16); + memset(str2,0,sizeof(char) * 32); + memset(wstr1,0,sizeof(wint_t) * 16); + memset(wstr2,0,sizeof(wint_t) * 32); p = &(self->sec_layer->client_mcs_data); p->p = p->data; - in_uint8s(p, 31); + in_uint8s(p, 23); + in_uint16_le(p, ud_type); + in_uint16_le(p, ud_length); + in_uint32_le(p, self->client_info.version); in_uint16_le(p, self->client_info.width); in_uint16_le(p, self->client_info.height); - in_uint8s(p, 120); - self->client_info.bpp = 8; + in_uint16_le(p, self->client_info.colorDepth); in_uint16_le(p, i); - switch (i) + in_uint32_le(p, self->client_info.keyboardLayout); + in_uint32_le(p, self->client_info.clientBuild); + /* read in the "clientName" field: (up to 15 unicode characters plus a terminating null character) */ + for (i = 0; i < 16; i++) { + in_uint16_le(p, self->client_info.clientName[i]); + hi = self->client_info.clientName[i] >> 8; + lo = self->client_info.clientName[i] & 0x00ff; + wstr1[i] = (wint_t)(utf16_to_utf32(hi, lo)); + hi = 0; + lo = 0; + } + in_uint32_le(p, self->client_info.keyboardType); + in_uint32_le(p, self->client_info.keyboardSubType); + in_uint32_le(p, self->client_info.keyboardFunctionKey); + /* read in the "imeFileName" field: (up to 31 unicode characters plus a terminating NULL) */ + for (i = 0; i < 32; i++) { + in_uint16_le(p, self->client_info.imeFileName[i]); + hi = self->client_info.imeFileName[i] >> 8; + lo = self->client_info.imeFileName[i] & 0x00ff; + wstr2[i] = (wint_t)(utf16_to_utf32(hi, lo)); + hi = 0; + lo = 0; + } + in_uint16_le(p, self->client_info.postBeta2ColorDepth); + in_uint16_le(p, self->client_info.clientProductId); + in_uint32_le(p, self->client_info.serialNumber); + in_uint16_le(p, self->client_info.highColorDepth); + in_uint16_le(p, self->client_info.supportedColorDepths); + in_uint16_le(p, self->client_info.earlyCapabilityFlags); + if ((self->client_info.earlyCapabilityFlags & RNS_UD_CS_VALID_CONNECTION_TYPE) != 0x0000) { + in_uint8a(p, self->client_info.clientDigProductId, 64); + in_uint8(p, self->client_info.connectionType); + } + + wcstombs(str1, (const wchar_t * restrict)(self->client_info.clientName), 16); + wcstombs(str2, (const wchar_t * restrict)(self->client_info.imeFileName), 32); + //MDBGLOG("sound","\n\n$$$$\n postBeta2ColorDepth=%8.8x;\n highColorDepth=%d;\n supportedColorDepths=%d;\n earlyCapabilityFlags=%d;\n keyboardType=%d;\n keyboardLayout=%d;\n colorDepth=%8.8x;\n connectionType=%d;\n clientName=%s;\n imeFileName=%s;\n version=%8.8x;\n length=%d;\n",self->client_info.postBeta2ColorDepth, self->client_info.highColorDepth, self->client_info.supportedColorDepths, self->client_info.earlyCapabilityFlags, self->client_info.keyboardType, self->client_info.keyboardLayout, self->client_info.colorDepth, self->client_info.connectionType, str1, str2, (unsigned int)(self->client_info.version), ud_length); + + self->client_info.bpp = 8; + switch (self->client_info.postBeta2ColorDepth) { + case 0xca00: + self->client_info.bpp = 4; + break; case 0xca01: - in_uint8s(p, 6); - in_uint8(p, i); - if (i > 8) + if (self->client_info.highColorDepth > 8) { - self->client_info.bpp = i; + self->client_info.bpp = self->client_info.highColorDepth; } break; case 0xca02: @@ -358,10 +440,17 @@ self->client_info.bpp = 24; break; } + if ((self->client_info.earlyCapabilityFlags & RNS_UD_CS_WANT_32BPP_SESSION) != 0x0000) { + self->client_info.bpp = 32; + } + p->p = p->data; - DEBUG(("client width %d, client height %d bpp %d", - self->client_info.width, self->client_info.height, - self->client_info.bpp)); + //MDBGLOG("sound","client width %d, client height %d bpp %d", + // self->client_info.width, self->client_info.height, + // self->client_info.bpp); + //DEBUG(("client width %d, client height %d bpp %d", + // self->client_info.width, self->client_info.height, + // self->client_info.bpp)); return 0; } @@ -423,12 +512,15 @@ caps_count++; out_uint16_le(s, RDP_CAPSET_GENERAL); /* 1 */ out_uint16_le(s, RDP_CAPLEN_GENERAL); /* 24(0x18) */ - out_uint16_le(s, 1); /* OS major type */ - out_uint16_le(s, 3); /* OS minor type */ + //out_uint16_le(s, 1); /* OS major type */ + //out_uint16_le(s, 3); /* OS minor type */ + out_uint16_le(s, OSMAJORTYPE_UNIX); /* OS major type */ + out_uint16_le(s, TS_OSMINORTYPE_NATIVE_XSERVER); /* OS minor type */ out_uint16_le(s, 0x200); /* Protocol version */ out_uint16_le(s, 0); /* pad */ out_uint16_le(s, 0); /* Compression types */ - out_uint16_le(s, 0); /* pad use 0x40d for rdp packets, 0 for not */ + //out_uint16_le(s, 0); /* pad use 0x40d for rdp packets, 0 for not */ + out_uint16_le(s, 0x40d); /* pad use 0x40d for rdp packets, 0 for not */ out_uint16_le(s, 0); /* Update capability */ out_uint16_le(s, 0); /* Remote unshare capability */ out_uint16_le(s, 0); /* Compression level */ @@ -487,10 +579,10 @@ out_uint8(s, 0); /* multi dest blt */ out_uint8(s, 0); /* multi pat blt */ out_uint8(s, 0); /* multi screen blt */ - out_uint8(s, 0); /* multi rect */ + out_uint8(s, 1); /* multi rect */ out_uint8(s, 0); /* fast index */ - out_uint8(s, 0); /* polygon */ - out_uint8(s, 0); /* polygon */ + out_uint8(s, 0); /* polygonSC ([MS-RDPEGDI], 2.2.2.2.1.1.2.16) */ + out_uint8(s, 0); /* polygonCB ([MS-RDPEGDI], 2.2.2.2.1.1.2.17) */ out_uint8(s, 0); /* polyline */ out_uint8(s, 0); /* unused */ out_uint8(s, 0); /* fast glyph */ @@ -644,11 +736,11 @@ xrdp_process_capset_bmpcache2(struct xrdp_rdp* self, struct stream* s, int len) { - int Bpp; - int i; + int Bpp = 0; + int i = 0; self->client_info.bitmap_cache_version = 2; - Bpp = (self->client_info.bpp + 7) / 8; + Bpp = (self->client_info.bpp == 32) ? 3 : (self->client_info.bpp + 7) / 8; in_uint16_le(s, i); self->client_info.bitmap_cache_persist_enable = i; in_uint8s(s, 2); /* number of caches in set, 3 */ @@ -1155,3 +1247,32 @@ DEBUG(("out xrdp_rdp_send_deactive")); return 0; } + +UTF32 utf16_to_utf32(UTF16 lead, UTF16 trail) { + const UTF32 SURROGATE_OFFSET = 0x10000 - (0xD800 << 10) - 0xDC00; + UTF32 rv = 0x00000000; + + // computations + rv = (lead << 10) + trail + SURROGATE_OFFSET; + + return rv; +} + +UTF16 * utf32_to_utf16(UTF32 codepoint) { + const UTF32 LEAD_OFFSET = 0xD800 - (0x10000 >> 10); + UTF16 * rv = (UTF16 *)NULL; + UTF16 lead = 0x0000; + UTF16 trail = 0x0000; + + rv = (UTF16 *)malloc(sizeof(UTF16) * 2); + rv[0] = 0x0000; + rv[1] = 0x0000; + + // computations + lead = LEAD_OFFSET + (codepoint >> 10); + trail = 0xDC00 + (codepoint & 0x3FF); + rv[0] = lead; + rv[1] = trail; + + return rv; +} diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/libxrdp/xrdp_sec.c posixrdp/posixxrdp.orig/libxrdp/xrdp_sec.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/libxrdp/xrdp_sec.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/libxrdp/xrdp_sec.c 2010-11-08 09:56:44.000000000 +0100 @@ -303,54 +303,80 @@ static int APP_CC xrdp_sec_process_logon_info(struct xrdp_sec* self, struct stream* s) { - int flags; - int len_domain; - int len_user; - int len_password; - int len_program; - int len_directory; - int len_ip; - int len_dll; - int tzone; + int flags = 0; + int len_domain = 0; + int len_user = 0; + int len_password = 0; + int len_program = 0; + int len_directory = 0; + int len_ip = 0; + int len_dll = 0; + int tzone = 0; char tmpdata[256]; - in_uint8s(s, 4); - in_uint32_le(s, flags); - DEBUG(("in xrdp_sec_process_logon_info flags $%x", flags)); + /* initialize (zero out) local variables */ + g_memset(tmpdata,0,sizeof(char)*256); + self->rdp_layer->client_info.clientAddress = (uint8_t *)g_malloc(sizeof(uint8_t) * 511,1); + self->rdp_layer->client_info.clientDir = (uint8_t *)g_malloc(sizeof(uint8_t) * 511,1); + + //in_uint8s(s, 4); /* skip over "CodePage" field */ + in_uint32_le(s, self->rdp_layer->client_info.CodePage); + in_uint32_le(s, self->rdp_layer->client_info.flags); + DEBUG(("in xrdp_sec_process_logon_info flags $%x", self->rdp_layer->client_info.flags)); /* this is the first test that the decrypt is working */ - if ((flags & RDP_LOGON_NORMAL) != RDP_LOGON_NORMAL) /* 0x33 */ + if ((self->rdp_layer->client_info.flags & (INFO_MOUSE | INFO_DISABLECTRLALTDEL | INFO_UNICODE | INFO_MAXIMIZESHELL)) != (INFO_MOUSE | INFO_DISABLECTRLALTDEL | INFO_UNICODE | INFO_MAXIMIZESHELL)) /* 0x33 */ { /* must be or error */ DEBUG(("xrdp_sec_process_logon_info: flags wrong, major error")); return 1; } - if (flags & RDP_LOGON_LEAVE_AUDIO) + if (self->rdp_layer->client_info.flags & INFO_REMOTECONSOLEAUDIO) { self->rdp_layer->client_info.sound_code = 1; - DEBUG(("flag RDP_LOGON_LEAVE_AUDIO found")); + DEBUG(("flag INFO_REMOTECONSOLEAUDIO found")); } - if ((flags & RDP_LOGON_AUTO) && (!self->rdp_layer->client_info.is_mce)) + if ((self->rdp_layer->client_info.flags & INFO_AUTOLOGON) && (!self->rdp_layer->client_info.is_mce)) /* todo, for now not allowing autologon and mce both */ { self->rdp_layer->client_info.rdp_autologin = 1; - DEBUG(("flag RDP_LOGON_AUTO found")); + DEBUG(("flag INFO_AUTOLOGON found")); } - if (flags & RDP_COMPRESSION) + if (self->rdp_layer->client_info.flags & INFO_COMPRESSION) { self->rdp_layer->client_info.rdp_compression = 1; - DEBUG(("flag RDP_COMPRESSION found")); + DEBUG(("flag INFO_COMPRESSION found")); } in_uint16_le(s, len_domain); + if (len_domain > 511) { + DEBUG(("ERROR [xrdp_sec_process_logon_info()]: len_domain > 511")); + return 1; + } in_uint16_le(s, len_user); + if (len_domain > 511) { + DEBUG(("ERROR [xrdp_sec_process_logon_info()]: len_domain > 511")); + return 1; + } in_uint16_le(s, len_password); + if (len_password > 511) { + DEBUG(("ERROR [xrdp_sec_process_logon_info()]: len_password > 511")); + return 1; + } in_uint16_le(s, len_program); + if (len_program > 511) { + DEBUG(("ERROR [xrdp_sec_process_logon_info()]: len_program > 511")); + return 1; + } in_uint16_le(s, len_directory); - /* todo, we should error out in any of the above lengths are > 512 */ + if (len_directory > 511) { + DEBUG(("ERROR [xrdp_sec_process_logon_info()]: len_directory > 511")); + return 1; + } + /* todo, we should error out if any of the above lengths are > 512 */ /* to avoid buffer overruns */ unicode_in(s, len_domain, self->rdp_layer->client_info.domain, 255); DEBUG(("domain %s", self->rdp_layer->client_info.domain)); unicode_in(s, len_user, self->rdp_layer->client_info.username, 255); DEBUG(("username %s", self->rdp_layer->client_info.username)); - if (flags & RDP_LOGON_AUTO) + if (self->rdp_layer->client_info.flags & RDP_LOGON_AUTO) { unicode_in(s, len_password, self->rdp_layer->client_info.password, 255); DEBUG(("flag RDP_LOGON_AUTO found")); @@ -363,21 +389,21 @@ DEBUG(("program %s", self->rdp_layer->client_info.program)); unicode_in(s, len_directory, self->rdp_layer->client_info.directory, 255); DEBUG(("directory %s", self->rdp_layer->client_info.directory)); - if (flags & RDP_LOGON_BLOB) + if (self->rdp_layer->client_info.flags & RDP_LOGON_BLOB) { - in_uint8s(s, 2); /* unknown */ - in_uint16_le(s, len_ip); - unicode_in(s, len_ip - 2, tmpdata, 255); - in_uint16_le(s, len_dll); - unicode_in(s, len_dll - 2, tmpdata, 255); - in_uint32_le(s, tzone); /* len of timetone */ - in_uint8s(s, 62); /* skip */ - in_uint8s(s, 22); /* skip misc. */ - in_uint8s(s, 62); /* skip */ - in_uint8s(s, 26); /* skip stuff */ + in_uint16_le(s,self->rdp_layer->client_info.clientAddressFamily); /* network address family (either CI_AF_INET or CI_AF_INET6) */ + in_uint16_le(s, self->rdp_layer->client_info.cbClientAddress); + unicode_in(s, self->rdp_layer->client_info.cbClientAddress - 2, self->rdp_layer->client_info.clientAddress, 255); + in_uint16_le(s, self->rdp_layer->client_info.cbClientDir); + unicode_in(s, self->rdp_layer->client_info.cbClientDir - 2, self->rdp_layer->client_info.clientDir, 255); + in_uint8s(s, 148); /* skip over timezone */ + in_uint32_le(s, self->rdp_layer->client_info.clientSessionId); in_uint32_le(s, self->rdp_layer->client_info.rdp5_performanceflags); + in_uint16_le(s, self->rdp_layer->client_info.cbAutoReconnectLen); + unicode_in(s, self->rdp_layer->client_info.cbAutoReconnectLen - 2, self->rdp_layer->client_info.autoReconnectCookie, 255); } - DEBUG(("out xrdp_sec_process_logon_info")); + //MDBGLOG("sound","\n ------\n\n * clientAddress: %s\n * clientDir: %s\n",self->rdp_layer->client_info.clientAddress,self->rdp_layer->client_info.clientDir); + //DEBUG(("out xrdp_sec_process_logon_info")); return 0; } @@ -386,7 +412,7 @@ static int APP_CC xrdp_sec_send_lic_initial(struct xrdp_sec* self) { - struct stream* s; + struct stream* s = (struct stream *)NULL; make_stream(s); init_stream(s, 8192); @@ -725,10 +751,10 @@ int APP_CC xrdp_sec_process_mcs_data(struct xrdp_sec* self) { - struct stream* s; - char* hold_p; - int tag; - int size; + struct stream* s = (struct stream *)NULL; + char* hold_p = (char *)NULL; + int tag = 0; + int size = 0; s = &self->client_mcs_data; /* set p to beginning */ @@ -861,13 +887,13 @@ static void APP_CC xrdp_sec_in_mcs_data(struct xrdp_sec* self) { - struct stream* s; - struct xrdp_client_info* client_info; - int index; - char c; + struct stream* s = (struct stream *)NULL; + struct xrdp_client_info* client_info = (struct xrdp_client_info *)NULL; + int index = 0; + char c = 0; - client_info = &self->rdp_layer->client_info; - s = &self->client_mcs_data; + client_info = &(self->rdp_layer->client_info); + s = &(self->client_mcs_data); /* get hostname, its unicode */ s->p = s->data; in_uint8s(s, 47); @@ -896,13 +922,15 @@ int APP_CC xrdp_sec_incoming(struct xrdp_sec* self) { - struct list* items; - struct list* values; - int index; - char* item; - char* value; + struct list* items = NULL; + struct list* values = NULL; + int index = 0; + char* item = NULL; + char* value = NULL; char key_file[256]; + g_memset(key_file,0,sizeof(char)*256); + DEBUG((" in xrdp_sec_incoming")); g_random(self->server_random, 32); items = list_create(); diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/linux/drivers/rdp.c posixrdp/posixxrdp.orig/linux/drivers/rdp.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/linux/drivers/rdp.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/linux/drivers/rdp.c 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,1617 @@ +#include +#include + +static struct rdp_tty * g_tty_driver = (struct rdp_tty *)NULL; +static DEFINE_MUTEX(g_tty_driver_mutex); + +static struct mutex * p_tty_mutex = (struct mutex *)NULL; +static struct rdp_port g_ports[MAX_PORT]; +static int g_port_count = 0; + +static struct mutex g_write_mutex = {}; +static struct mutex * p_write_mutex = (struct mutex *)NULL; + +static struct rdp_cmd * g_cmds[16]; +static struct rdp_cmd * g_pend[16]; +static struct rdp_irq_entry * g_read[16]; +static struct rdp_write_entry * g_write[16]; +static completed_cmd_list_t * g_compl[16]; +static struct rdp_cb_entry * g_cb[16]; +static int g_initialized = 0; + +static int rdp_receive(struct rdp_port *, int, int, char *); +static void __cb_enq(struct rdp_cb_entry *); +static void cb_enq(struct rdp_cb_entry *); +static struct rdp_cb_entry * __cb_deq(struct rdp_cb_entry **); +static struct rdp_cb_entry * cb_deq(struct rdp_cb_entry **); +static void read_enq(struct rdp_irq_entry *); +static struct rdp_irq_entry * read_deq(struct rdp_irq_entry **); +static void write_enq(struct rdp_write_entry *); +static struct rdp_write_entry * write_deq(struct rdp_write_entry **); +static struct list_head * compl_enq(completed_cmd_list_t *); +static completed_cmd_list_t * __compl_deq(completed_cmd_list_t **); +static completed_cmd_list_t * compl_deq(completed_cmd_list_t **); + +#define Q_NAME "rdp_workq" +static void rdp_cmdw_handler(struct work_struct *); +static struct workqueue_struct * g_cmdq = (struct workqueue_struct *)NULL; +static DECLARE_WORK(g_cmdw, rdp_cmdw_handler); + +#define COMPLQ_NAME "rdp_compq" +static void rdp_complw_handler(struct work_struct *); +static struct workqueue_struct * g_complq = (struct workqueue_struct *)NULL; +//static DECLARE_DELAYED_WORK(g_complw, rdp_complw_handler); +static DECLARE_WORK(g_complw, rdp_complw_handler); + +#define READQ_NAME "rdp_readq" +static void rdp_readw_handler(struct work_struct *); +static struct workqueue_struct * g_readq = (struct workqueue_struct *)NULL; +static DECLARE_WORK(g_readw, rdp_readw_handler); + +#define WRITEQ_NAME "rdp_writeq" +static void rdp_writew_handler(struct work_struct *); +static struct workqueue_struct * g_writeq = (struct workqueue_struct *)NULL; +static DECLARE_WORK(g_writew, rdp_writew_handler); + +static struct list_head * p_enq(struct rdp_cmd *); + +static const char * cmdarray[] = CMD_TO_STRING_ARRAY_DEF; + +static LIST_HEAD(rdp_completed_cmds); +static DEFINE_SPINLOCK(rdp_completed_cmds_lock); + +static LIST_HEAD(rdp_read_list); +static DEFINE_SPINLOCK(rdp_read_lock); +static LIST_HEAD(rdp_write_list); +static DEFINE_SPINLOCK(rdp_write_lock); + +static DEFINE_MUTEX(g_cb_mutex); +static struct mutex * p_cb_mutex = (struct mutex *)NULL; + + +/*** + *** Netlink Connection ("cn") functions + ***/ + +static struct rdp_family rdp_default_family = {}; + +static DEFINE_SPINLOCK(rdp_flock); +static DEFINE_SPINLOCK(rdp_cmd_lock); +static LIST_HEAD(rdp_families); +static LIST_HEAD(rdp_outbound_cmd_list); +static LIST_HEAD(rdp_pending_cmd_list); + +#define CBQ_NAME "rdp_cbq" +static void rdp_cn_callback_bh(CBARGS); +static LIST_HEAD(rdp_cb_list); +static DEFINE_SPINLOCK(rdp_cb_lock); +static void rdp_cbw_handler(struct work_struct *); +static struct workqueue_struct * g_cbq = (struct workqueue_struct *)NULL; +static DECLARE_WORK(g_cbw, rdp_cbw_handler); + + +static void rdp_cn_callback(CBARGS) { + struct rdp_cb_entry * cb_entry = (struct rdp_cb_entry *)NULL; + unsigned char * buf = (unsigned char *)NULL; + unsigned char * sbuf = (unsigned char *)NULL; + struct cn_msg * lmsg = (struct cn_msg *)NULL; + + if (imsg == NULL || g_initialized < 1) { + goto end; + } + cb_entry = (struct rdp_cb_entry *)kzalloc((sizeof(struct rdp_cb_entry) + imsg->len + 1), GFP_ATOMIC); + if (cb_entry == NULL) { + goto end; + } + else { + if (parms != NULL) { + memcpy(&(cb_entry->parms), parms, sizeof(struct netlink_skb_parms)); + } + lmsg = &(cb_entry->imsg); + buf = (unsigned char *)(lmsg + 1); + sbuf = (unsigned char *)(imsg + 1); +// memcpy(&(cb_entry->imsg), imsg, (sizeof(struct cn_msg) + imsg->len)); + memcpy(lmsg, imsg, sizeof(struct cn_msg)); + memcpy(buf, sbuf, imsg->len); + } + + cb_enq(cb_entry); + queue_work(g_cbq, &g_cbw); + + end:; +} + +static void rdp_cbw_handler(struct work_struct * work) { + struct rdp_cb_entry * cb = (struct rdp_cb_entry *)NULL; + + if (work == NULL || g_initialized < 1 || p_cb_mutex == NULL) { + goto end; + } + mutex_lock(p_cb_mutex); + cb_deq(&cb); + if (cb != NULL) { + rdp_cn_callback_bh(&(cb->imsg), &(cb->parms)); + } + mutex_unlock(p_cb_mutex); + + end:; +} + +static void rdp_cn_callback_bh(CBARGS) { + unsigned long flags; + int found = 0; + int mlen = 0; + int i = 0; + int lcompleted = 0; + uint8_t mtype = 0x00; + int status = 0; + struct cn_msg * msg = (struct cn_msg *)imsg; + rdp_netlink_msg * m = (rdp_netlink_msg *)(msg + 1); + struct device * gdev = (struct device *)NULL; + if (msg == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: msg is a null pointer", __func__); + goto end; + } + mutex_lock(&(g_tty_driver_mutex)); + if (g_tty_driver != NULL) { + //smp_rmb(); + status = atomic_read(&(g_tty_driver->status)); + } + else { + status = RDP_STATUS_EXIT; + } + if (g_tty_driver == NULL || status != RDP_STATUS_NORMAL) { + } + else if (msg != NULL) { + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + while (msg->len) { + rdp_reg_num id; + struct rdp_cmd * cmd = (struct rdp_cmd *)NULL; + memcpy(&id, m->id.id, sizeof(rdp_reg_num)); + mtype |= m->type; + mlen = m->len; + if (msg->ack > 0 && mtype < 0x81) { + spin_lock_irqsave(&rdp_cmd_lock, flags); + for (i = 0; i < 16; i++) { + cmd = g_pend[i]; + if (cmd != NULL) { + DBGLOG(KERN_INFO "INFO\t[%s()]: cmd->seqid = %d", __func__, cmd->seqid); + //smp_rmb(); + lcompleted = atomic_read(&(cmd->completed)); + if (cmd->seqid == msg->seq && lcompleted < 1) { + smp_mb__before_atomic_inc(); + atomic_inc(&(cmd->completed)); + found = 1; + g_pend[i] = NULL; + break; + } + } + } + spin_unlock_irqrestore(&rdp_cmd_lock, flags); + if (likely(found > 0 && cmd != NULL)) { + completed_cmd_list_t * cmd_item = (completed_cmd_list_t *)NULL; + DBGLOG(KERN_INFO "INFO\t[%s()]: cmd found, queueing callback...", __func__); + if (cmd != NULL && cmd->aux != NULL) { + cmd_item = (completed_cmd_list_t *)(cmd->aux); + cmd->aux = (void *)NULL; + } + else { + cmd_item = (completed_cmd_list_t *)kzalloc(sizeof(completed_cmd_list_t), GFP_KERNEL); + } + cmd_item->cmd = cmd; + if (cmd != NULL && cmd->odata != NULL && cmd->olen > 0 && m->data != NULL && mlen > 0 && cmd->odata != m->data && cmd->olen == mlen) { + memcpy(cmd->odata, m->data, MINVAL(cmd->olen, mlen)); + DBGLOG(KERN_INFO "INFO\t[%s()]: cmd->odata = %p; cmd->olen = %d; m->data = %p; m->len = %d", __func__, cmd->odata, cmd->olen, m->data, m->len); + } + compl_enq(cmd_item); + queue_work(g_complq, &g_complw); + } + else { + //DBGLOG(KERN_INFO "INFO\t[%s()]: cmd not found! (%d)", __func__, msg->seq); + } + } + else if (mtype > 0 && m != NULL) { + /* if an unsolicited cn packet is received, then it should be handled as a + * "virtual interrupt" received from the userspace daemon; so, queue up an + * ersatz irq handler: + */ + struct rdp_irq_data * irq_data = (struct rdp_irq_data *)(m->data); + struct rdp_irq_entry * irq_entry = (struct rdp_irq_entry *)NULL; + DBGLOG(KERN_INFO "INFO\t[%s()]: (IRQ)", __func__); + mtype &= ~RDP_ASYNC; + switch (mtype) { + case RDP_ADDPORT: + { + int i = 0; + DBGLOG(KERN_INFO "INFO\t[%s()]: calling tty_register_device()", __func__); + if (p_tty_mutex != NULL) { + mutex_lock(p_tty_mutex); + } + i = g_port_count; + if (!(gdev = tty_register_device((struct tty_driver *)(g_tty_driver->driver), i, NULL))) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: tty_register_device() failed", __func__); + } + else if (g_ports[i].initialized > 0) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: port is already initialized", __func__); + } + else { + DBGLOG(KERN_INFO "INFO\t[%s()]: tty_register_device() was successful", __func__); + memset(&(g_ports[i]), 0, sizeof(struct rdp_port)); + mutex_init(&(g_ports[i].mut)); + mutex_lock(&(g_ports[i].mut)); + g_ports[i].initialized = 1; + g_ports[i].g_ports_index = i; + spin_lock_init(&(g_ports[i].cmd_lock)); + spin_lock_init(&(g_ports[i].status_lock)); + //smp_wmb(); + atomic_set(&(g_ports[i].open_count), 0); + g_ports[i].rec.port = &(g_ports[i]); + g_ports[i].rec.tty = g_ports[i].item; + g_ports[i].rec.initialized = 1; + g_ports[i].rec.owner = THIS_MODULE; + if (g_tty_driver != NULL && g_tty_driver->driver != NULL && g_tty_driver->driver->name != NULL) { + scnprintf(g_ports[i].rec.name, RDP_MAXNAMELEN, "%s%d", g_tty_driver->driver->name, i); + } + spin_lock_init(&(g_ports[i].rec.lock)); + mutex_unlock(&(g_ports[i].mut)); + g_port_count++; + } + if (p_tty_mutex != NULL) { + mutex_unlock(p_tty_mutex); + } + } + break; + case RDP_RXFULL: + { + int idx = 0; + int found = 0; + const int nr = MAX_PORT; + if (p_tty_mutex != NULL) { + mutex_lock(p_tty_mutex); + } + for (idx = 0; idx < nr; idx++) { + if (g_ports[idx].device_id == irq_data->device_id) { + found = 1; + break; + } + } + irq_entry = (struct rdp_irq_entry *)kzalloc(sizeof(struct rdp_irq_entry), GFP_KERNEL); + if (irq_entry != NULL) { + irq_entry->data = irq_data; + if (found > 0) { + irq_entry->port = &(g_ports[idx]); + } + else { + irq_entry->port = &(g_ports[0]); + } + read_enq(irq_entry); + queue_work(g_readq, &g_readw); + } + if (p_tty_mutex != NULL) { + mutex_unlock(p_tty_mutex); + } + } + break; + default: + { + DBGLOG(KERN_WARNING "WARNING\t[%s()]: INTERRUPT --> unrecognized opcode (\"0x%02x\")", __func__, mtype); + } + break; + } + } + msg->len -= (sizeof(rdp_netlink_msg) + m->len); + m = (rdp_netlink_msg *)(((u8 *)m) + m->len); + } + } + mutex_unlock(&(g_tty_driver_mutex)); + + end:; + DBGLOG(KERN_INFO "INFO\t[%s()]: done.", __func__); +} + + +static int rdp_netlink_send(struct rdp_record * dev, rdp_netlink_msg * msg, int seq, int memmode) { + unsigned long flags; + int rv = 0; + char buf[512]; + struct cn_msg * m = (struct cn_msg *)buf; + rdp_netlink_msg * w = (rdp_netlink_msg *)(m+1); + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + if (dev == NULL) { + DBGLOG(KERN_WARNING "WARNING\t[%s()]: dev is a null pointer", __func__); + rv = -EINVAL; + goto end; + } + if (msg == NULL) { + DBGLOG(KERN_WARNING "WARNING\t[%s()]: msg is a null pointer", __func__); + rv = -EINVAL; + goto end; + } + memset(buf, 0, sizeof(buf)); + m->id.idx = CN_IDX_RDP; + m->id.val = CN_VAL_RDP; + spin_lock_irqsave(&(dev->lock), flags); + m->seq = seq; + spin_unlock_irqrestore(&(dev->lock), flags); + rv = m->seq; + m->len = sizeof(rdp_netlink_msg) + msg->len; + DBGLOG(KERN_INFO "INFO\t[%s()]: about to call memcpy()...", __func__); + memcpy(w, msg, m->len); + DBGLOG(KERN_INFO "INFO\t[%s()]: about to call cn_netlink_send()... {m->len = \"%d\"}", __func__, m->len); + cn_netlink_send(m, 0, memmode); + end: + DBGLOG(KERN_INFO "INFO\t[%s()]: done (rv = \"%d\").", __func__, rv); + return rv; +} + +static int rdp_init_netlink(void) { + int rv = 0; + struct cb_id rdp_id = { + .idx = CN_IDX_RDP, + .val = CN_VAL_RDP, + }; + spin_lock_init(&(rdp_default_family.lock)); + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + rv = cn_add_callback(&rdp_id, "rdp", &rdp_cn_callback); + DBGLOG(KERN_INFO "INFO\t[%s()]: done.", __func__); + return rv; +} + +static void rdp_stop_netlink(void) { + struct cb_id rdp_id = { + .idx = CN_IDX_RDP, + .val = CN_VAL_RDP, + }; + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + cn_del_callback(&rdp_id); + DBGLOG(KERN_INFO "INFO\t[%s()]: done.", __func__); +} + +int rdp_register_family(struct rdp_family * newf) { + unsigned long flags; + struct list_head * ent = (struct list_head *)NULL; + struct list_head * n = (struct list_head *)NULL; + struct rdp_family * f = (struct rdp_family *)NULL; + int ret = 0; + + spin_lock_irqsave(&rdp_flock, flags); + list_for_each_safe(ent, n, &rdp_families) { + f = list_entry(ent, struct rdp_family, family_entry); + if (f->fid == newf->fid) { + ret = -EEXIST; + break; + } + } + + if (!ret) { + //smp_wmb(); + atomic_set(&newf->refcnt, 0); + newf->need_exit = 0; + list_add_tail(&newf->family_entry, &rdp_families); + } + spin_unlock_irqrestore(&rdp_flock, flags); + + return ret; +} + +void rdp_unregister_family(struct rdp_family * fent) { + unsigned long flags; + struct list_head * ent = (struct list_head *)NULL; + struct list_head * n = (struct list_head *)NULL; + struct rdp_family * f = (struct rdp_family *)NULL; + int refcnt = 0; + + spin_lock_irqsave(&rdp_flock, flags); + list_for_each_safe(ent, n, &rdp_families) { + f = list_entry(ent, struct rdp_family, family_entry); + if (f->fid == fent->fid) { + list_del(&fent->family_entry); + break; + } + } + + fent->need_exit = 1; + + spin_unlock_irqrestore(&rdp_flock, flags); + + //smp_rmb(); + refcnt = atomic_read(&(fent->refcnt)); + while (refcnt) { + printk(KERN_INFO "Waiting for family %u to become free: refcnt=%d.\n", fent->fid, atomic_read(&fent->refcnt)); + if (msleep_interruptible(1000)) { + flush_signals(current); + } + //smp_rmb(); + refcnt = atomic_read(&(fent->refcnt)); + } +} + +/* + * Should be called under rdp_flock held. + */ +struct rdp_family * rdp_family_registered(u8 fid) { + struct list_head * ent = (struct list_head *)NULL; + struct list_head * n = (struct list_head *)NULL; + struct rdp_family * f = (struct rdp_family *)NULL; + int ret = 0; + list_for_each_safe(ent, n, &rdp_families) { + f = list_entry(ent, struct rdp_family, family_entry); + if (f->fid == fid) { + ret = 1; + break; + } + } + return (ret) ? f : NULL; +} + +static void __rdp_family_put(struct rdp_family * f) { + int tmp = 0; + smp_mb__before_atomic_dec(); + tmp = atomic_dec_and_test(&f->refcnt); + if (tmp) { + f->need_exit = 1; + } +} + +void rdp_family_put(struct rdp_family * f) { + spin_lock(&rdp_flock); + __rdp_family_put(f); + spin_unlock(&rdp_flock); +} + +static void __rdp_family_get(struct rdp_family *f) { + smp_mb__before_atomic_inc(); + atomic_inc(&(f->refcnt)); +} + +void rdp_family_get(struct rdp_family *f) { + spin_lock(&rdp_flock); + __rdp_family_get(f); + spin_unlock(&rdp_flock); +} + +/*****/ +/*****/ + +static int cmd_output(struct rdp_cmd * rcmd, int memmode) { + unsigned long flags; + int rv = 0; + struct rdp_record * rec = (struct rdp_record *)NULL; + struct rdp_family * f = (struct rdp_family *)NULL; + unsigned char * cbuf = (unsigned char *)NULL; + void * data = (void *)NULL; + int len = 0; + rdp_netlink_msg msg; + unsigned char cmd = 0x00; + struct rdp_port * port = (struct rdp_port *)NULL; + struct tty_struct * tty = (struct tty_struct *)NULL; + int ilen = 0; + int olen = 0; + void * idata = (void *)NULL; + void * odata = (void *)NULL; + uint32_t cmd_idx = 0x00000000; + + if (rcmd == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: rcmd is a NULL pointer", __func__); + rv = -EINVAL; + goto end; + } + else { + port = rcmd->port; + cmd = rcmd->cmd; + tty = rcmd->tty; + ilen = rcmd->ilen; + olen = rcmd->olen; + idata = rcmd->idata; + odata = rcmd->odata; + len = ilen; + data = idata; + cmd_idx = rcmd->cmd_idx; + } + if (ilen > 0 && idata == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: idata is a NULL pointer", __func__); + rv = -EINVAL; + goto end; + } + if (olen > 0 && odata == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: odata is a NULL pointer", __func__); + rv = -ENOMEM; + goto end; + } + if (cmd == RDP_PING || cmd > RDP_XCHAR) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: opcode not implemented (\"%8.8x\")", __func__, cmd); + rv = -EINVAL; + goto end; + } + + DBGLOG(KERN_INFO "INFO\t[%s()]: called (cmd = \"%s\", %d)", __func__, RDPCMD(cmd), cmd); + + rec = &(rcmd->port->rec); + + memset(&msg, 0, sizeof(rdp_netlink_msg)); + //smp_wmb(); + atomic_set(&(rec->refcnt), 0); + INIT_COMPLETION(rec->released); + + spin_lock_irqsave(&rdp_flock, flags); + f = &rdp_default_family; + __rdp_family_get(f); + rec->family = f; + spin_unlock_irqrestore(&rdp_flock, flags); + + msg.type = cmd; + + if (len > 0 && data != NULL) { + msg.len = len + sizeof(uint32_t); + cbuf = (unsigned char *)kzalloc((sizeof(rdp_netlink_msg) + len), memmode); + if (cbuf == NULL) { + rv = -ENOMEM; + goto end; + } + else { + rdp_netlink_msg * pm = (rdp_netlink_msg *)cbuf; + uint32_t * pn = (uint32_t *)(pm+1); + unsigned char * pd = (unsigned char *)(pn+1); + memcpy(pm, &msg, sizeof(rdp_netlink_msg)); + memcpy(pn, &cmd_idx, sizeof(uint32_t)); + memcpy(pd, data, len); + } + } + else { + cbuf = (unsigned char *)kzalloc((sizeof(rdp_netlink_msg) + sizeof(uint32_t)), memmode); + if (cbuf == NULL) { + rv = -ENOMEM; + goto end; + } + else { + rdp_netlink_msg * pm = (rdp_netlink_msg *)cbuf; + uint32_t * pn = (uint32_t *)(pm+1); + memcpy(pm, &msg, sizeof(rdp_netlink_msg)); + memcpy(pn, &cmd_idx, sizeof(uint32_t)); + } + } + INIT_LIST_HEAD(&(rcmd->list)); + rcmd->seqid = rec->seq++; + p_enq(rcmd); + DBGLOG(KERN_INFO "INFO\t[%s()]: about to call rdp_netlink_send()...", __func__); + rv = rdp_netlink_send(rec, (void *)cbuf, rcmd->seqid, memmode); + DBGLOG(KERN_INFO "INFO\t[%s()]: (\" returned)", __func__); + + if (cbuf != NULL) { + kfree(cbuf); + } + + end: + DBGLOG(KERN_INFO "INFO\t[%s()]: done (rv = \"%d\")", __func__, rv); + return rv; +} + + +static struct list_head * __compl_enq(completed_cmd_list_t * cmd_item) { + struct list_head * rv = (struct list_head *)NULL; + int found = 0; + int i = 0; + + if (cmd_item != NULL) { + for (i = 0; i < 16; i++) { + if (g_compl[i] == NULL) { + found = 1; + break; + } + } + if (found) { + g_compl[i] = cmd_item; + } + else { + rv = NULL; + } + } + + return rv; +} + +static struct list_head * compl_enq(completed_cmd_list_t * cmd_item) { + unsigned long flags; + struct list_head * rv = (struct list_head *)NULL; + + spin_lock_irqsave(&rdp_completed_cmds_lock, flags); + if (likely(cmd_item != NULL)) { + rv = __compl_enq(cmd_item); + } + spin_unlock_irqrestore(&rdp_completed_cmds_lock, flags); + + return rv; +} + +static completed_cmd_list_t * __compl_deq(completed_cmd_list_t ** rcmd) { + completed_cmd_list_t * rv = (completed_cmd_list_t *)NULL; + int i = 0; + + for (i = 0; i < 16; i++) { + if (g_compl[i] != NULL) { + rv = g_compl[i]; + g_compl[i] = (completed_cmd_list_t *)NULL; + break; + } + } + + /* + if (list_empty(&rdp_completed_cmds)) { + rv = (completed_cmd_list_t *)NULL; + } + else { + rv = list_entry(rdp_completed_cmds.next, completed_cmd_list_t, list); + } + if (rv != NULL) { + list_del_init(&(rv->list)); + } + */ + + if (rcmd != NULL) { + *rcmd = rv; + } + + return rv; +} + +static completed_cmd_list_t * compl_deq(completed_cmd_list_t ** rcmd) { + unsigned long flags; + completed_cmd_list_t * rv = (completed_cmd_list_t *)NULL; + + spin_lock_irqsave(&rdp_completed_cmds_lock, flags); + rv = __compl_deq(rcmd); + spin_unlock_irqrestore(&rdp_completed_cmds_lock, flags); + + return rv; +} + + +static struct list_head * cmd_enq(struct rdp_cmd * rcmd) { + unsigned long flags; + int i = 0; + int found = 0; + struct list_head * rv = &rdp_outbound_cmd_list; + + if (rcmd != NULL) { + spin_lock_irqsave(&rdp_cmd_lock, flags); + for (i = 0; i < 16; i++) { + if (g_cmds[i] == NULL) { + found = 1; + break; + } + } + if (found) { + g_cmds[i] = rcmd; + } + else { + rv = NULL; + } + spin_unlock_irqrestore(&rdp_cmd_lock, flags); + } + + return rv; +} + +static struct rdp_cmd * cmd_deq(struct rdp_cmd ** rcmd) { + unsigned long flags; + int i = 0; + struct rdp_cmd * rv = (struct rdp_cmd *)NULL; + + spin_lock_irqsave(&rdp_cmd_lock, flags); + for (i = 0; i < 16; i++) { + if (g_cmds[i] != NULL) { + rv = g_cmds[i]; + g_cmds[i] = (struct rdp_cmd *)NULL; + break; + } + } + spin_unlock_irqrestore(&rdp_cmd_lock, flags); + + if (rcmd != NULL) { + *rcmd = rv; + } + + return rv; +} + +static void read_enq(struct rdp_irq_entry * irq_entry) { + unsigned long flags; + int found = 0; + int i = 0; + + if (irq_entry != NULL) { + spin_lock_irqsave(&rdp_read_lock, flags); + for (i = 0; i < 16; i++) { + if (g_read[i] == NULL) { + found = 1; + break; + } + } + if (found) { + g_read[i] = irq_entry; + } + else { + //rv = NULL; + } + spin_unlock_irqrestore(&rdp_read_lock, flags); + } + + + /* + if (irq_entry != NULL) { + INIT_LIST_HEAD(&(irq_entry->list)); + spin_lock_irqsave(&rdp_read_lock, flags); + list_add_tail(&(irq_entry->list), &rdp_read_list); + spin_unlock_irqrestore(&rdp_read_lock, flags); + } + */ +} + +static struct rdp_irq_entry * read_deq(struct rdp_irq_entry ** itm) { + unsigned long flags; + struct rdp_irq_entry * rv = (struct rdp_irq_entry *)NULL; + int i = 0; + + spin_lock_irqsave(&rdp_read_lock, flags); + for (i = 0; i < 16; i++) { + if (g_read[i] != NULL) { + rv = g_read[i]; + g_read[i] = (struct rdp_irq_entry *)NULL; + break; + } + } + spin_unlock_irqrestore(&rdp_read_lock, flags); + + /* + spin_lock_irqsave(&rdp_read_lock, flags); + rv = list_entry(rdp_read_list.next, struct rdp_irq_entry, list); + if (rv != NULL) { + list_del_init(&(rv->list)); + } + spin_unlock_irqrestore(&rdp_read_lock, flags); + */ + + if (itm != NULL) { + *itm = rv; + } + + return rv; +} + +static void write_enq(struct rdp_write_entry * write_entry) { + unsigned long flags; + int found = 0; + int i = 0; + + if (write_entry != NULL) { + spin_lock_irqsave(&rdp_write_lock, flags); + for (i = 0; i < 16; i++) { + if (g_write[i] == NULL) { + found = 1; + break; + } + } + if (found) { + g_write[i] = write_entry; + } + else { + //rv = NULL; + } + spin_unlock_irqrestore(&rdp_write_lock, flags); + } + + /* + if (write_entry != NULL) { + INIT_LIST_HEAD(&(write_entry->list)); + spin_lock_irqsave(&rdp_write_lock, flags); + list_add_tail(&(write_entry->list), &rdp_write_list); + spin_unlock_irqrestore(&rdp_write_lock, flags); + } + */ +} + +static struct rdp_write_entry * write_deq(struct rdp_write_entry ** itm) { + unsigned long flags; + struct rdp_write_entry * rv = (struct rdp_write_entry *)NULL; + int i = 0; + + spin_lock_irqsave(&rdp_write_lock, flags); + for (i = 0; i < 16; i++) { + if (g_write[i] != NULL) { + rv = g_write[i]; + g_write[i] = (struct rdp_write_entry *)NULL; + break; + } + } + spin_unlock_irqrestore(&rdp_write_lock, flags); + + /* + spin_lock_irqsave(&rdp_write_lock, flags); + rv = list_entry(rdp_write_list.next, struct rdp_write_entry, list); + if (rv != NULL) { + list_del_init(&(rv->list)); + } + spin_unlock_irqrestore(&rdp_write_lock, flags); + */ + + if (itm != NULL) { + *itm = rv; + } + + return rv; +} + +static void __cb_enq(struct rdp_cb_entry * cb_entry) { + int found = 0; + int i = 0; + + if (cb_entry != NULL) { + for (i = 0; i < 16; i++) { + if (g_cb[i] == NULL) { + found = 1; + break; + } + } + if (found) { + g_cb[i] = cb_entry; + } + else { + //rv = NULL; + } + } + + /* + if (cb_entry != NULL) { + INIT_LIST_HEAD(&(cb_entry->list)); + spin_lock_irqsave(&rdp_cb_lock, flags); + list_add_tail(&(cb_entry->list), &rdp_cb_list); + spin_unlock_irqrestore(&rdp_cb_lock, flags); + } + */ +} + +static void cb_enq(struct rdp_cb_entry * cb_entry) { + unsigned long flags; + + spin_lock_irqsave(&rdp_cb_lock, flags); + __cb_enq(cb_entry); + spin_unlock_irqrestore(&rdp_cb_lock, flags); +} + + +static struct rdp_cb_entry * __cb_deq(struct rdp_cb_entry ** itm) { + struct rdp_cb_entry * rv = (struct rdp_cb_entry *)NULL; + int i = 0; + + for (i = 0; i < 16; i++) { + if (g_cb[i] != NULL) { + rv = g_cb[i]; + g_cb[i] = (struct rdp_cb_entry *)NULL; + break; + } + } + + /* + rv = list_entry(rdp_cb_list.next, struct rdp_cb_entry, list); + if (rv != NULL) { + list_del_init(&(rv->list)); + } + */ + + if (itm != NULL) { + *itm = rv; + } + + return rv; +} + +static struct rdp_cb_entry * cb_deq(struct rdp_cb_entry ** itm) { + unsigned long flags; + struct rdp_cb_entry * rv = (struct rdp_cb_entry *)NULL; + + spin_lock_irqsave(&rdp_cb_lock, flags); + __cb_deq(&rv); + if (itm != NULL) { + *itm = rv; + } + spin_unlock_irqrestore(&rdp_cb_lock, flags); + + return rv; +} + + +static struct list_head * p_enq(struct rdp_cmd * rcmd) { + unsigned long flags; + int i = 0; + int found = 0; + struct list_head * rv = &rdp_outbound_cmd_list; + + if (rcmd != NULL) { + + spin_lock_irqsave(&rdp_cmd_lock, flags); + + for (i = 0; i < 16; i++) { + if (g_pend[i] == NULL) { + found = 1; + break; + } + } + + if (found) { + g_pend[i] = rcmd; + } + else { + rv = NULL; + } + + spin_unlock_irqrestore(&rdp_cmd_lock, flags); + } + + return rv; +} + +#ifdef DO_PDEQ + +static struct rdp_cmd * p_deq(struct rdp_cmd ** rcmd) { + unsigned long flags; + int i = 0; + struct rdp_cmd * rv = (struct rdp_cmd *)NULL; + + spin_lock_irqsave(&rdp_cmd_lock, flags); + for (i = 0; i < 16; i++) { + if (g_pend[i] != NULL) { + rv = g_pend[i]; + g_pend[i] = (struct rdp_cmd *)NULL; + break; + } + } + spin_unlock_irqrestore(&rdp_cmd_lock, flags); + + if (rcmd != NULL) { + *rcmd = rv; + } + + return rv; +} + +#endif + + +static int cmd_process_list(struct list_head * cmdlist) { + int rv = 0; + struct rdp_cmd * cmd = (struct rdp_cmd *)NULL; + + might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + + if (g_tty_driver != NULL) { + do { + cmd_deq(&cmd); + if (cmd != NULL) { + DBGLOG(KERN_INFO "INFO\t[%s()]: outputting RDP command", __func__); +// cmd_output(cmd, GFP_ATOMIC); + cmd_output(cmd, GFP_KERNEL); + } + } while (cmd != NULL); + } + + DBGLOG(KERN_INFO "INFO\t[%s()]: done.", __func__); + + return rv; +} + +static struct rdp_cmd * cmd_send(struct rdp_port * port, unsigned char cmd, void * idata, int ilen, void * odata, int olen, int memmode) { + int seqid = 0; + int cmd_idx = 0; + struct rdp_cmd * lcmd = (struct rdp_cmd *)NULL; + + DBGLOG(KERN_INFO "INFO\t[%s()]: called (cmd = \"%s\", ilen = \"%d\", olen = \"%d\")", __func__, RDPCMD(cmd), ilen, olen); + + if (port == NULL) { + goto end; + } + + lcmd = (struct rdp_cmd *)kzalloc(sizeof(struct rdp_cmd), memmode); + + if (lcmd == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: lcmd == NULL", __func__); + goto end; + } + + spin_lock_init(&(lcmd->lock)); + lcmd->cmd = cmd; + lcmd->port = port; + lcmd->idata = idata; + lcmd->ilen = ilen; + lcmd->odata = odata; + lcmd->olen = olen; + lcmd->cmd_idx = cmd_idx; + lcmd->aux = (void *)kzalloc(sizeof(completed_cmd_list_t), memmode); + //smp_wmb(); + atomic_set(&(lcmd->completed), 0); + + if (olen > 0 && lcmd->odata == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: lcmd->odata == NULL", __func__); + goto end; + } + + DBGLOG(KERN_INFO "INFO\t[%s()]: about to call cmd_enq()...", __func__); + cmd_enq(lcmd); + DBGLOG(KERN_INFO "INFO\t[%s()]: cmd_enq() returned", __func__); + + end:; + DBGLOG(KERN_INFO "INFO\t[%s()]: done (lcmd = \"%p\", seqid = \"%d\").", __func__, lcmd, seqid); + return lcmd; +} + + +static int __cmd_exec(struct rdp_port * port, unsigned char cmd, void * idata, int ilen, void * odata, int olen, int memmode) { + unsigned long flags; + int rv = 0; + int seqid = 0; + int lcompleted = 0x00000000; + int cnt = 0; + const unsigned int max_timeout = 2000; /* in jiffies: 1 jiffy = 0.004 sec */ + struct rdp_cmd * lcmd = (struct rdp_cmd *)NULL; + DECLARE_COMPLETION_ONSTACK(tdone); + struct completion * ldone = (struct completion *)NULL; + //struct work_struct * lwork = (struct work_struct *)NULL; + //DECLARE_WORK(g_cmdw, rdp_cmdw_handler); + struct work_struct twork; + struct work_struct * lwork = &twork; + + DBGLOG(KERN_INFO "INFO\t[%s()]: called (cmd = \"%s\", ilen = \"%d\", olen = \"%d\")", __func__, RDPCMD(cmd), ilen, olen); + + if (port == NULL) { + rv = -EINVAL; + goto end; + } + +// ldone = (struct completion *)kzalloc(sizeof(struct completion), memmode); + ldone = &tdone; + if (ldone == NULL) { + rv = -ENOMEM; + goto end; + } + else { +// init_completion(ldone); + } + + DBGLOG(KERN_INFO "INFO\t[%s()]: about to call cmd_send()...", __func__); + lcmd = cmd_send(port, cmd, idata, ilen, odata, olen, memmode); + DBGLOG(KERN_INFO "INFO\t[%s()]: cmd_send() returned", __func__); + if (lcmd == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: \"lcmd\" is a NULL pointer", __func__); + goto end; + } + lcmd->done = ldone; + DBGLOG(KERN_INFO "INFO\t[%s()]: queue_delayed_work() returned", __func__); + +// lwork = (struct work_struct *)kzalloc(sizeof(struct work_struct), memmode); + if (lwork == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: \"lwork\" is a NULL pointer", __func__); + goto end; + } +// INIT_WORK(lwork, rdp_cmdw_handler); + INIT_WORK_ON_STACK(lwork, rdp_cmdw_handler); + + do { + DBGLOG(KERN_INFO "INFO\t[%s()]: waiting for completion... (%d)", __func__, cnt); +// queue_work(g_cmdq, &g_cmdw); + queue_work(g_cmdq, lwork); + wait_for_completion_interruptible_timeout(ldone, max_timeout); + flush_workqueue(g_cmdq); +// spin_lock_irqsave(&(lcmd->lock), flags); +// INIT_COMPLETION(*ldone); + INIT_COMPLETION(tdone); + //smp_rmb(); + lcompleted = atomic_read(&(lcmd->completed)); +// spin_unlock_irqrestore(&(lcmd->lock), flags); + cnt++; + } while (!(lcompleted) && cnt < 5); + if (!lcompleted) { + int i = 0; + spin_lock_irqsave(&rdp_cmd_lock, flags); + for (i = 0; i < 16; i++) { + if (g_cmds[i] == lcmd) { + g_cmds[i] = (struct rdp_cmd *)NULL; + kfree(lcmd); + lcmd = (struct rdp_cmd *)NULL; + } + } + spin_unlock_irqrestore(&rdp_cmd_lock, flags); + } + DBGLOG(KERN_INFO "INFO\t[%s()]: (\" completed)", __func__); + if (lwork != NULL) { + //kfree(lwork); + } + + if (lcmd != NULL && lcmd->olen > 0 && lcmd->odata != NULL && olen > 0 && odata != NULL && odata != lcmd->odata) { + memcpy(odata, lcmd->odata, MINVAL(lcmd->olen,olen)); + } + if (lcmd != NULL) { + memset(lcmd, 0, sizeof(struct rdp_cmd)); + kfree(lcmd); + } + + end:; + DBGLOG(KERN_INFO "INFO\t[%s()]: done (rv = \"%d\", seqid = \"%d\").", __func__, rv, seqid); + return rv; +} + +static int cmd_exec(struct rdp_port * port, unsigned char cmd, void * idata, int ilen, void * odata, int olen) { + might_sleep(); + return __cmd_exec(port, cmd, idata, ilen, odata, olen, GFP_KERNEL); +} + + +#define DO_RECEIVE 1 +#ifdef DO_RECEIVE + +static int rdp_receive(struct rdp_port * port, int stat, int buflen, char * buf) { + int rv = 1; + unsigned char ch = 0; + struct tty_struct * tty = port->item; + + DBGLOG(KERN_INFO "INFO\t[%s()]: called (stat = \"%d\", buflen = \"%d\")", __func__, stat, buflen); + + if (port == NULL || tty == NULL) { + rv = -EINVAL; + goto end; + } + + if (buflen == 1 && buf != NULL) { + ch = buf[0]; + tty_flip_buffer_push(tty); + tty_insert_flip_char(tty, ch, 0); + tty_flip_buffer_push(tty); + } + else if (buflen > 1 && buf != NULL) { + tty_flip_buffer_push(tty); + tty_insert_flip_string(tty, buf, buflen); + tty_flip_buffer_push(tty); + } + + + end: + return rv; +} + +#endif + + +static int supp_write(struct tty_struct * tty, const unsigned char * buffer, int count) { + unsigned long flags; + int rv = 0; + int cnt = 0; + int done = 0; + struct rdp_port * port = (struct rdp_port *)NULL; + struct work_struct * lwork = (struct work_struct *)NULL; + const unsigned int max_timeout = 2000; /* in jiffies: 1 jiffy = 0.004 sec */ + +// might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + + if (tty != NULL && tty->index > -1 && tty->index < MAX_PORT) { + port = &(g_ports[tty->index]); + } + if (port == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: tty->index out of range", __func__); + rv = -ENOMEM; + goto end; + } + else if (port->initialized < 1 || atomic_read(&(port->open_count)) < 1) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: port is not open", __func__); + rv = -EACCES; + goto end; + } + else { + struct rdp_write_entry * write_entry = (struct rdp_write_entry *)NULL; + + if (p_write_mutex != NULL) { +// mutex_lock(p_write_mutex); + } + +// write_entry = (struct rdp_write_entry *)kzalloc(sizeof(struct rdp_write_entry), GFP_ATOMIC); + write_entry = (struct rdp_write_entry *)kzalloc(sizeof(struct rdp_write_entry), GFP_KERNEL); + spin_lock_init(&(write_entry->lock)); +// spin_lock_irqsave(&(write_entry->lock), flags); + write_entry->port = port; + write_entry->len = count; + write_entry->data = (unsigned char *)buffer; + write_entry->rv = 0; + write_entry->completed = 0; + init_completion(&(write_entry->done)); + + write_enq(write_entry); +// spin_unlock_irqrestore(&(write_entry->lock), flags); + //spin_lock_irqsave(&rdp_write_lock, flags); + //queue_work(g_writeq, &g_writew); + //spin_unlock_irqrestore(&rdp_write_lock, flags); + do { + lwork = (struct work_struct *)kzalloc(sizeof(struct work_struct), GFP_KERNEL); + INIT_WORK(lwork, rdp_writew_handler); + DBGLOG(KERN_INFO "INFO\t[%s()]: waiting for completion... (%d)", __func__, cnt); + queue_work(g_writeq, lwork); +// wait_for_completion_interruptible_timeout(&(write_entry->done), max_timeout); +// wait_for_completion_timeout(&(write_entry->done), max_timeout); +// flush_workqueue(g_writeq); + spin_lock_irqsave(&(write_entry->lock), flags); + if (write_entry->completed > 0) { + done = 1; + kfree(lwork); + lwork = (struct work_struct *)NULL; + } + else { + done = 0; + write_entry->canceled = 1; + } +// INIT_COMPLETION(write_entry->done); + spin_unlock_irqrestore(&(write_entry->lock), flags); + cnt++; + } while (!done && cnt < 3); + + if (p_write_mutex != NULL) { +// mutex_unlock(p_write_mutex); + } + + rv = count; + } + + end:; + return rv; +} + +static int supp_open(struct tty_struct * tty, struct file * file) { + int rv = 0; + uint32_t fd = 0; + int oc = 0; + struct rdp_port * port = (struct rdp_port *)NULL; + + might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + + if (likely(tty != NULL && tty->index > -1 && tty->index < MAX_PORT)) { + port = &(g_ports[tty->index]); + } + if (unlikely(port == NULL)) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: tty->index out of range", __func__); + rv = -ENOMEM; + goto end; + } + else { + + if (likely(port->initialized == 1 && port->item == NULL)) { + port->item = tty; + port->rec.tty = port->item; + port->rec.port = port; + port->fp = file; + } + + //smp_rmb(); + oc = atomic_read(&(port->open_count)); + cmd_exec(port, RDP_OPEN, NULL, 0, &fd, sizeof(fd)); + DBGLOG(KERN_INFO "INFO\t[%s()]: fd = %d", __func__, fd); + rv = fd; + if (oc == 0) { + cmd_exec(port, RDP_START, NULL, 0, NULL, 0); + } + smp_mb__before_atomic_inc(); + atomic_inc(&(port->open_count)); + + } + + end:; + DBGLOG(KERN_INFO "INFO\t[%s()]: done.", __func__); + return rv; +} + +static void supp_close(struct tty_struct * tty, struct file * file) { + int oc = 0; + struct rdp_port * port = (struct rdp_port *)NULL; + + might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + + if (likely(tty != NULL && tty->index > -1 && tty->index < MAX_PORT && g_ports[tty->index].initialized > 0)) { + port = &(g_ports[tty->index]); + } + if (unlikely(port == NULL || port->item == NULL || port->initialized < 1)) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: port or port->item is NULL or not initialized", __func__); + } + else { + //smp_rmb(); + oc = atomic_read(&(port->open_count)); + if (oc == 1) { + cmd_exec(port, RDP_STOP, NULL, 0, NULL, 0); + } + cmd_exec(port, RDP_CLOSE, NULL, 0, NULL, 0); + smp_mb__before_atomic_dec(); + atomic_dec(&(port->open_count)); + } +} + +int __init rdp_ops_setup(struct tty_operations * ops) { + int rv = 0; + + if (ops == NULL) { + rv = -EINVAL; + goto exit; + } + ops->open = supp_open; + ops->close = supp_close; + ops->write = supp_write; + + exit:; + return rv; +} + +int __init rdp_init(struct tty_driver * drv, struct mutex * tty_mutex) { + int rv = 0; + + might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + + //mutex_lock(&(g_tty_driver_mutex)); + + if (p_tty_mutex == NULL) { + p_tty_mutex = tty_mutex; + } + p_write_mutex = &g_write_mutex; + memset(p_write_mutex, 0x00, sizeof(struct mutex)); + //mutex_init(p_write_mutex); + + memset(g_ports, 0, sizeof(g_ports)); + memset(g_cmds, 0, sizeof(g_cmds)); + memset(g_pend, 0, sizeof(g_pend)); + memset(g_read, 0, sizeof(g_read)); + memset(g_write, 0, sizeof(g_write)); + memset(g_compl, 0, sizeof(g_compl)); + memset(g_cb, 0, sizeof(g_cb)); + + g_tty_driver = (struct rdp_tty *)kzalloc(sizeof(struct rdp_tty), GFP_KERNEL); + //mutex_init(&(g_tty_driver_mutex)); + //mutex_lock(&(g_tty_driver_mutex)); + g_tty_driver->driver = drv; + if (p_cb_mutex == NULL) { + memset(&g_cb_mutex, 0x00, sizeof(struct mutex)); + p_cb_mutex = &g_cb_mutex; + } + //mutex_init(p_cb_mutex); + //mutex_lock(p_cb_mutex); + //smp_wmb(); + atomic_set(&(g_tty_driver->status), RDP_STATUS_LOADING); + g_cbq = create_singlethread_workqueue(CBQ_NAME); + g_cmdq = create_singlethread_workqueue(Q_NAME); + g_complq = create_singlethread_workqueue(COMPLQ_NAME); + g_readq = create_singlethread_workqueue(READQ_NAME); + g_writeq = create_singlethread_workqueue(WRITEQ_NAME); + //smp_wmb(); + atomic_set(&(g_tty_driver->status), RDP_STATUS_NORMAL); + g_initialized = 1; + //mutex_unlock(p_cb_mutex); + rdp_init_netlink(); + //mutex_unlock(&(g_tty_driver_mutex)); + + DBGLOG(KERN_INFO "INFO\t[%s()]: done.", __func__); + return rv; +} + +void __exit rdp_exit(struct tty_driver * tty) { + struct rdp_tty * l_tty_driver = (struct rdp_tty *)NULL; + might_sleep(); + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + //mutex_lock(&(g_tty_driver_mutex)); + if (g_tty_driver != NULL && g_initialized > 0) { + l_tty_driver = g_tty_driver; + //smp_wmb(); + atomic_set(&(g_tty_driver->status), RDP_STATUS_EXIT); + } + g_initialized = 0; + //mutex_unlock(&(g_tty_driver_mutex)); + destroy_workqueue(g_cbq); + destroy_workqueue(g_writeq); + destroy_workqueue(g_readq); + destroy_workqueue(g_cmdq); + destroy_workqueue(g_complq); + //mutex_lock(&(g_tty_driver_mutex)); + if (g_tty_driver != NULL) { + if (g_tty_driver->driver != NULL) { + int i = 0; + for (i = 0; i < MAX_PORT; i++) { + if (g_ports[i].initialized) { + //mutex_lock(&(g_ports[i].mut)); + tty_unregister_device(g_tty_driver->driver, i); + g_ports[i].initialized = 0; + //mutex_unlock(&(g_ports[i].mut)); + } + } + } + g_tty_driver->driver = (struct tty_driver *)NULL; + g_tty_driver = (struct rdp_tty *)NULL; + //mutex_unlock(&(l_tty_driver->mut)); + memset(g_tty_driver, 0, sizeof(struct rdp_tty)); + kfree(l_tty_driver); + l_tty_driver = (struct rdp_tty *)NULL; + } + rdp_stop_netlink(); + p_cb_mutex = (struct mutex *)NULL; + DBGLOG(KERN_INFO "INFO\t[%s()]: done.", __func__); +} + +static void rdp_cmdw_handler(struct work_struct * work) { + unsigned long status = RDP_STATUS_ERROR; + //mutex_lock(&(g_tty_driver_mutex)); + if (g_tty_driver != NULL) { + //smp_rmb(); + status = atomic_read(&(g_tty_driver->status)); + if (g_tty_driver != NULL && status == RDP_STATUS_NORMAL) { + cmd_process_list(&rdp_outbound_cmd_list); + } + } + //mutex_unlock(&(g_tty_driver_mutex)); +} + +/* +static void rdp_complw_handler_old(struct work_struct * work) { + unsigned long flags; + completed_cmd_list_t * cmd_item = (completed_cmd_list_t *)NULL; + int lcompleted = 0; + struct list_head * ent = (struct list_head *)NULL; + struct list_head * n = (struct list_head *)NULL; + + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + + spin_lock_irqsave(&rdp_completed_cmds_lock, flags); + list_for_each_safe(ent, n, &rdp_completed_cmds) { + if (list_empty(&rdp_completed_cmds)) { + cmd_item = NULL; + } + else { + cmd_item = list_entry(ent, completed_cmd_list_t, list); + } + if (cmd_item != NULL && cmd_item->cmd != NULL) { + struct rdp_cmd * cmd = cmd_item->cmd; + //smp_rmb(); + lcompleted = atomic_read(&(cmd->completed)); + if (lcompleted == 1) { + smp_mb__before_atomic_inc(); + atomic_inc(&(cmd->completed)); + DBGLOG(KERN_INFO "INFO\t[%s()]: completing a cmd...", __func__); +// complete_all(cmd->done); + complete(cmd->done); + DBGLOG(KERN_INFO "INFO\t[%s()]: (completed)", __func__); + } + list_del_init(&(cmd_item->list)); + } + } + spin_unlock_irqrestore(&rdp_completed_cmds_lock, flags); + + DBGLOG(KERN_INFO "INFO\t[%s()]: done.", __func__); +} +*/ + +static void rdp_complw_handler(struct work_struct * work) { + unsigned long flags; + completed_cmd_list_t * cmd_item = (completed_cmd_list_t *)NULL; + int lcompleted = 0; + int i = 0; + + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + + spin_lock_irqsave(&rdp_completed_cmds_lock, flags); + for (i = 0; i < 16; i++) { + cmd_item = g_compl[i]; + if (cmd_item != NULL && cmd_item->cmd != NULL) { + struct rdp_cmd * cmd = (struct rdp_cmd *)NULL; + cmd = cmd_item->cmd; + //spin_lock(&(cmd->lock)); + //smp_rmb(); + lcompleted = atomic_read(&(cmd->completed)); + if (lcompleted >= 1) { + smp_mb__before_atomic_inc(); + atomic_inc(&(cmd->completed)); + if (cmd->done != NULL) { + DBGLOG(KERN_INFO "INFO\t[%s()]: completing a cmd...", __func__); + complete_all(cmd->done); + DBGLOG(KERN_INFO "INFO\t[%s()]: (completed)", __func__); + } + g_compl[i] = (completed_cmd_list_t *)NULL; + } + //spin_unlock(&(cmd->lock)); + } + } + spin_unlock_irqrestore(&rdp_completed_cmds_lock, flags); + + DBGLOG(KERN_INFO "INFO\t[%s()]: done.", __func__); +} + +static void rdp_readw_handler(struct work_struct * work) { + struct rdp_irq_entry * irq_entry = (struct rdp_irq_entry *)NULL; + struct rdp_irq_data * irq_data = (struct rdp_irq_data *)NULL; + struct tty_struct * tty = (struct tty_struct *)NULL; + unsigned char mut_locked = 0; + + might_sleep(); + + if (p_tty_mutex != NULL) { + //mutex_lock(p_tty_mutex); + mut_locked = 1; + } + //mutex_lock(&(g_tty_driver_mutex)); + if (g_tty_driver != NULL && mut_locked > 0) { + if (g_tty_driver->driver != NULL) { + read_deq(&irq_entry); + if (irq_entry != NULL) { + irq_data = irq_entry->data; + if (irq_entry->port != NULL && irq_data != NULL && irq_data->rx_len > 0 && irq_data->rx_buf != NULL && irq_entry->port->item != NULL && irq_entry->port->item->driver_data != NULL) { + struct rdptty_serial * rdp = (struct rdptty_serial *)NULL; + tty = irq_entry->port->item; + rdp = (struct rdptty_serial *)(tty->driver_data); + if (rdp != NULL) { + //mutex_lock(&(rdp->mut)); + rdp_receive(irq_entry->port, 0, irq_data->rx_len, irq_data->rx_buf); + //mutex_unlock(&(rdp->mut)); + } + } + } + } + } + mutex_unlock(&(g_tty_driver_mutex)); + if (p_tty_mutex != NULL && mut_locked > 0) { + mutex_unlock(p_tty_mutex); + } +} + +static void rdp_writew_handler(struct work_struct * work) { + unsigned long flags; + struct rdp_port * port = (struct rdp_port *)NULL; + struct rdp_write_entry * write_entry = (struct rdp_write_entry *)NULL; + unsigned char * buf = (unsigned char *)NULL; + int len = 0; + unsigned char mut_locked = 0; + int rv = 0; + + might_sleep(); + + if (p_tty_mutex != NULL) { + mutex_lock(p_tty_mutex); + mut_locked = 1; + } + mutex_lock(&(g_tty_driver_mutex)); + if (g_tty_driver != NULL && mut_locked > 0) { + if (g_tty_driver->driver != NULL) { + write_deq(&write_entry); + if (write_entry != NULL) { + spin_lock_irqsave(&(write_entry->lock), flags); + } + if (write_entry != NULL && write_entry->data != NULL && write_entry->len > 0 && write_entry->canceled != 1 && write_entry->completed < 1) { + port = write_entry->port; + len = write_entry->len; + buf = write_entry->data; + if (port != NULL && buf != NULL && len > 0) { + DBGLOG(KERN_INFO "INFO\t[%s()]: about to call cmd_exec(RDP_WRITE)...", __func__); + spin_unlock_irqrestore(&(write_entry->lock), flags); + cmd_exec(port, RDP_WRITE, buf, len, &rv, sizeof(int)); + spin_lock_irqsave(&(write_entry->lock), flags); + DBGLOG(KERN_INFO "INFO\t[%s()]: rv = %d", __func__, rv); + } + write_entry->rv = rv; + write_entry->completed = 1; + complete_all(&(write_entry->done)); + } + if (write_entry != NULL) { + spin_unlock_irqrestore(&(write_entry->lock), flags); + } + } + } + mutex_unlock(&(g_tty_driver_mutex)); + if (p_tty_mutex != NULL && mut_locked > 0) { + mutex_unlock(p_tty_mutex); + } +} diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/linux/drivers/serial/Kconfig posixrdp/posixxrdp.orig/linux/drivers/serial/Kconfig --- xrdp/xrdp-0.5.0~20100303cvs.orig/linux/drivers/serial/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/linux/drivers/serial/Kconfig 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,1510 @@ +# +# Serial device configuration +# + +menu "Serial drivers" + depends on HAS_IOMEM + +config SERIAL_RDPUART + tristate "Virtual UART support for Remote Desktop Protocol device redirection" + select SERIAL_CORE + select CONNECTOR + default m + help + For enabling serial port redirection by xrdp. If in doubt, + it is safe to select "n". + +config SERIAL_TINY + tristate "Demo TTY device" + select SERIAL_CORE + default m + help + Demonstration TTY device driver. If in doubt, + it is safe to select "n". + +# +# The new 8250/16550 serial drivers +config SERIAL_8250 + tristate "8250/16550 and compatible serial support" + select SERIAL_CORE + ---help--- + This selects whether you want to include the driver for the standard + serial ports. The standard answer is Y. People who might say N + here are those that are setting up dedicated Ethernet WWW/FTP + servers, or users that have one of the various bus mice instead of a + serial mouse and don't intend to use their machine's standard serial + port for anything. (Note that the Cyclades and Stallion multi + serial port drivers do not need this driver built in for them to + work.) + + To compile this driver as a module, choose M here: the + module will be called 8250. + [WARNING: Do not compile this driver as a module if you are using + non-standard serial ports, since the configuration information will + be lost when the driver is unloaded. This limitation may be lifted + in the future.] + + BTW1: If you have a mouseman serial mouse which is not recognized by + the X window system, try running gpm first. + + BTW2: If you intend to use a software modem (also called Winmodem) + under Linux, forget it. These modems are crippled and require + proprietary drivers which are only available under Windows. + + Most people will say Y or M here, so that they can use serial mice, + modems and similar devices connecting to the standard serial ports. + +config SERIAL_8250_CONSOLE + bool "Console on 8250/16550 and compatible serial port" + depends on SERIAL_8250=y + select SERIAL_CORE_CONSOLE + ---help--- + If you say Y here, it will be possible to use a serial port as the + system console (the system console is the device which receives all + kernel messages and warnings and which allows logins in single user + mode). This could be useful if some terminal or printer is connected + to that serial port. + + Even if you say Y here, the currently visible virtual console + (/dev/tty0) will still be used as the system console by default, but + you can alter that using a kernel command line option such as + "console=ttyS1". (Try "man bootparam" or see the documentation of + your boot loader (grub or lilo or loadlin) about how to pass options + to the kernel at boot time.) + + If you don't have a VGA card installed and you say Y here, the + kernel will automatically use the first serial line, /dev/ttyS0, as + system console. + + You can set that using a kernel command line option such as + "console=uart8250,io,0x3f8,9600n8" + "console=uart8250,mmio,0xff5e0000,115200n8". + and it will switch to normal serial console when the corresponding + port is ready. + "earlycon=uart8250,io,0x3f8,9600n8" + "earlycon=uart8250,mmio,0xff5e0000,115200n8". + it will not only setup early console. + + If unsure, say N. + +config FIX_EARLYCON_MEM + bool + depends on X86 + default y + +config SERIAL_8250_GSC + tristate + depends on SERIAL_8250 && GSC + default SERIAL_8250 + +config SERIAL_8250_PCI + tristate "8250/16550 PCI device support" if EMBEDDED + depends on SERIAL_8250 && PCI + default SERIAL_8250 + help + This builds standard PCI serial support. You may be able to + disable this feature if you only need legacy serial support. + Saves about 9K. + +config SERIAL_8250_PNP + tristate "8250/16550 PNP device support" if EMBEDDED + depends on SERIAL_8250 && PNP + default SERIAL_8250 + help + This builds standard PNP serial support. You may be able to + disable this feature if you only need legacy serial support. + +config SERIAL_8250_HP300 + tristate + depends on SERIAL_8250 && HP300 + default SERIAL_8250 + +config SERIAL_8250_CS + tristate "8250/16550 PCMCIA device support" + depends on PCMCIA && SERIAL_8250 + ---help--- + Say Y here to enable support for 16-bit PCMCIA serial devices, + including serial port cards, modems, and the modem functions of + multi-function Ethernet/modem cards. (PCMCIA- or PC-cards are + credit-card size devices often used with laptops.) + + To compile this driver as a module, choose M here: the + module will be called serial_cs. + + If unsure, say N. + +config SERIAL_8250_NR_UARTS + int "Maximum number of 8250/16550 serial ports" + depends on SERIAL_8250 + default "4" + help + Set this to the number of serial ports you want the driver + to support. This includes any ports discovered via ACPI or + PCI enumeration and any ports that may be added at run-time + via hot-plug, or any ISA multi-port serial cards. + +config SERIAL_8250_RUNTIME_UARTS + int "Number of 8250/16550 serial ports to register at runtime" + depends on SERIAL_8250 + range 0 SERIAL_8250_NR_UARTS + default "4" + help + Set this to the maximum number of serial ports you want + the kernel to register at boot time. This can be overridden + with the module parameter "nr_uarts", or boot-time parameter + 8250.nr_uarts + +config SERIAL_8250_EXTENDED + bool "Extended 8250/16550 serial driver options" + depends on SERIAL_8250 + help + If you wish to use any non-standard features of the standard "dumb" + driver, say Y here. This includes HUB6 support, shared serial + interrupts, special multiport support, support for more than the + four COM 1/2/3/4 boards, etc. + + Note that the answer to this question won't directly affect the + kernel: saying N will just cause the configurator to skip all + the questions about serial driver options. If unsure, say N. + +config SERIAL_8250_MANY_PORTS + bool "Support more than 4 legacy serial ports" + depends on SERIAL_8250_EXTENDED && !IA64 + help + Say Y here if you have dumb serial boards other than the four + standard COM 1/2/3/4 ports. This may happen if you have an AST + FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available + from ), or other custom + serial port hardware which acts similar to standard serial port + hardware. If you only use the standard COM 1/2/3/4 ports, you can + say N here to save some memory. You can also say Y if you have an + "intelligent" multiport card such as Cyclades, Digiboards, etc. + +# +# Multi-port serial cards +# + +config SERIAL_8250_FOURPORT + tristate "Support Fourport cards" + depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS + help + Say Y here if you have an AST FourPort serial board. + + To compile this driver as a module, choose M here: the module + will be called 8250_fourport. + +config SERIAL_8250_ACCENT + tristate "Support Accent cards" + depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS + help + Say Y here if you have an Accent Async serial board. + + To compile this driver as a module, choose M here: the module + will be called 8250_accent. + +config SERIAL_8250_BOCA + tristate "Support Boca cards" + depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS + help + Say Y here if you have a Boca serial board. Please read the Boca + mini-HOWTO, available from + + To compile this driver as a module, choose M here: the module + will be called 8250_boca. + +config SERIAL_8250_EXAR_ST16C554 + tristate "Support Exar ST16C554/554D Quad UART" + depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS + help + The Uplogix Envoy TU301 uses this Exar Quad UART. If you are + tinkering with your Envoy TU301, or have a machine with this UART, + say Y here. + + To compile this driver as a module, choose M here: the module + will be called 8250_exar_st16c554. + +config SERIAL_8250_HUB6 + tristate "Support Hub6 cards" + depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS + help + Say Y here if you have a HUB6 serial board. + + To compile this driver as a module, choose M here: the module + will be called 8250_hub6. + +config SERIAL_8250_SHARE_IRQ + bool "Support for sharing serial interrupts" + depends on SERIAL_8250_EXTENDED + help + Some serial boards have hardware support which allows multiple dumb + serial ports on the same board to share a single IRQ. To enable + support for this in the serial driver, say Y here. + +config SERIAL_8250_DETECT_IRQ + bool "Autodetect IRQ on standard ports (unsafe)" + depends on SERIAL_8250_EXTENDED + help + Say Y here if you want the kernel to try to guess which IRQ + to use for your serial port. + + This is considered unsafe; it is far better to configure the IRQ in + a boot script using the setserial command. + + If unsure, say N. + +config SERIAL_8250_RSA + bool "Support RSA serial ports" + depends on SERIAL_8250_EXTENDED + help + ::: To be written ::: + +config SERIAL_8250_MCA + tristate "Support 8250-type ports on MCA buses" + depends on SERIAL_8250 != n && MCA + help + Say Y here if you have a MCA serial ports. + + To compile this driver as a module, choose M here: the module + will be called 8250_mca. + +config SERIAL_8250_ACORN + tristate "Acorn expansion card serial port support" + depends on ARCH_ACORN && SERIAL_8250 + help + If you have an Atomwide Serial card or Serial Port card for an Acorn + system, say Y to this option. The driver can handle 1, 2, or 3 port + cards. If unsure, say N. + +config SERIAL_8250_AU1X00 + bool "Au1x00 serial port support" + depends on SERIAL_8250 != n && SOC_AU1X00 + help + If you have an Au1x00 SOC based board and want to use the serial port, + say Y to this option. The driver can handle up to 4 serial ports, + depending on the SOC. If unsure, say N. + +config SERIAL_8250_RM9K + bool "Support for MIPS RM9xxx integrated serial port" + depends on SERIAL_8250 != n && SERIAL_RM9000 + select SERIAL_8250_SHARE_IRQ + help + Selecting this option will add support for the integrated serial + port hardware found on MIPS RM9122 and similar processors. + If unsure, say N. + +comment "Non-8250 serial port support" + +config SERIAL_AMBA_PL010 + tristate "ARM AMBA PL010 serial port support" + depends on ARM_AMBA && (BROKEN || !ARCH_VERSATILE) + select SERIAL_CORE + help + This selects the ARM(R) AMBA(R) PrimeCell PL010 UART. If you have + an Integrator/AP or Integrator/PP2 platform, or if you have a + Cirrus Logic EP93xx CPU, say Y or M here. + + If unsure, say N. + +config SERIAL_AMBA_PL010_CONSOLE + bool "Support for console on AMBA serial port" + depends on SERIAL_AMBA_PL010=y + select SERIAL_CORE_CONSOLE + ---help--- + Say Y here if you wish to use an AMBA PrimeCell UART as the system + console (the system console is the device which receives all kernel + messages and warnings and which allows logins in single user mode). + + Even if you say Y here, the currently visible framebuffer console + (/dev/tty0) will still be used as the system console by default, but + you can alter that using a kernel command line option such as + "console=ttyAM0". (Try "man bootparam" or see the documentation of + your boot loader (lilo or loadlin) about how to pass options to the + kernel at boot time.) + +config SERIAL_AMBA_PL011 + tristate "ARM AMBA PL011 serial port support" + depends on ARM_AMBA + select SERIAL_CORE + help + This selects the ARM(R) AMBA(R) PrimeCell PL011 UART. If you have + an Integrator/PP2, Integrator/CP or Versatile platform, say Y or M + here. + + If unsure, say N. + +config SERIAL_AMBA_PL011_CONSOLE + bool "Support for console on AMBA serial port" + depends on SERIAL_AMBA_PL011=y + select SERIAL_CORE_CONSOLE + ---help--- + Say Y here if you wish to use an AMBA PrimeCell UART as the system + console (the system console is the device which receives all kernel + messages and warnings and which allows logins in single user mode). + + Even if you say Y here, the currently visible framebuffer console + (/dev/tty0) will still be used as the system console by default, but + you can alter that using a kernel command line option such as + "console=ttyAMA0". (Try "man bootparam" or see the documentation of + your boot loader (lilo or loadlin) about how to pass options to the + kernel at boot time.) + +config SERIAL_SB1250_DUART + tristate "BCM1xxx on-chip DUART serial support" + depends on SIBYTE_SB1xxx_SOC=y + select SERIAL_CORE + default y + ---help--- + Support for the asynchronous serial interface (DUART) included in + the BCM1250 and derived System-On-a-Chip (SOC) devices. Note that + the letter D in DUART stands for "dual", which is how the device + is implemented. Depending on the SOC configuration there may be + one or more DUARTs available of which all are handled. + + If unsure, say Y. To compile this driver as a module, choose M here: + the module will be called sb1250-duart. + +config SERIAL_SB1250_DUART_CONSOLE + bool "Support for console on a BCM1xxx DUART serial port" + depends on SERIAL_SB1250_DUART=y + select SERIAL_CORE_CONSOLE + default y + ---help--- + If you say Y here, it will be possible to use a serial port as the + system console (the system console is the device which receives all + kernel messages and warnings and which allows logins in single user + mode). + + If unsure, say Y. + +config SERIAL_ATMEL + bool "AT91 / AT32 on-chip serial port support" + depends on (ARM && ARCH_AT91) || AVR32 + select SERIAL_CORE + help + This enables the driver for the on-chip UARTs of the Atmel + AT91 and AT32 processors. + +config SERIAL_ATMEL_CONSOLE + bool "Support for console on AT91 / AT32 serial port" + depends on SERIAL_ATMEL=y + select SERIAL_CORE_CONSOLE + help + Say Y here if you wish to use an on-chip UART on a Atmel + AT91 or AT32 processor as the system console (the system + console is the device which receives all kernel messages and + warnings and which allows logins in single user mode). + +config SERIAL_ATMEL_PDC + bool "Support DMA transfers on AT91 / AT32 serial port" + depends on SERIAL_ATMEL + default y + help + Say Y here if you wish to use the PDC to do DMA transfers to + and from the Atmel AT91 / AT32 serial port. In order to + actually use DMA transfers, make sure that the use_dma_tx + and use_dma_rx members in the atmel_uart_data struct is set + appropriately for each port. + + Note that break and error handling currently doesn't work + properly when DMA is enabled. Make sure that ports where + this matters don't use DMA. + +config SERIAL_ATMEL_TTYAT + bool "Install as device ttyATn instead of ttySn" + depends on SERIAL_ATMEL=y + help + Say Y here if you wish to have the internal AT91 / AT32 UARTs + appear as /dev/ttyATn (major 204, minor starting at 154) + instead of the normal /dev/ttySn (major 4, minor starting at + 64). This is necessary if you also want other UARTs, such as + external 8250/16C550 compatible UARTs. + The ttySn nodes are legally reserved for the 8250 serial driver + but are often misused by other serial drivers. + + To use this, you should create suitable ttyATn device nodes in + /dev/, and pass "console=ttyATn" to the kernel. + + Say Y if you have an external 8250/16C550 UART. If unsure, say N. + +config SERIAL_KS8695 + bool "Micrel KS8695 (Centaur) serial port support" + depends on ARCH_KS8695 + select SERIAL_CORE + help + This selects the Micrel Centaur KS8695 UART. Say Y here. + +config SERIAL_KS8695_CONSOLE + bool "Support for console on KS8695 (Centaur) serial port" + depends on SERIAL_KS8695=y + select SERIAL_CORE_CONSOLE + help + Say Y here if you wish to use a KS8695 (Centaur) UART as the + system console (the system console is the device which + receives all kernel messages and warnings and which allows + logins in single user mode). + +config SERIAL_CLPS711X + tristate "CLPS711X serial port support" + depends on ARM && ARCH_CLPS711X + select SERIAL_CORE + help + ::: To be written ::: + +config SERIAL_CLPS711X_CONSOLE + bool "Support for console on CLPS711X serial port" + depends on SERIAL_CLPS711X=y + select SERIAL_CORE_CONSOLE + help + Even if you say Y here, the currently visible virtual console + (/dev/tty0) will still be used as the system console by default, but + you can alter that using a kernel command line option such as + "console=ttyCL1". (Try "man bootparam" or see the documentation of + your boot loader (lilo or loadlin) about how to pass options to the + kernel at boot time.) + +config SERIAL_SAMSUNG + tristate "Samsung SoC serial support" + depends on ARM && PLAT_S3C + select SERIAL_CORE + help + Support for the on-chip UARTs on the Samsung S3C24XX series CPUs, + providing /dev/ttySAC0, 1 and 2 (note, some machines may not + provide all of these ports, depending on how the serial port + pins are configured. + +config SERIAL_SAMSUNG_UARTS + int + depends on ARM && PLAT_S3C + default 2 if ARCH_S3C2400 + default 4 if ARCH_S5PC1XX || ARCH_S3C64XX || CPU_S3C2443 + default 3 + help + Select the number of available UART ports for the Samsung S3C + serial driver + +config SERIAL_SAMSUNG_DEBUG + bool "Samsung SoC serial debug" + depends on SERIAL_SAMSUNG && DEBUG_LL + help + Add support for debugging the serial driver. Since this is + generally being used as a console, we use our own output + routines that go via the low-level debug printascii() + function. + +config SERIAL_SAMSUNG_CONSOLE + bool "Support for console on Samsung SoC serial port" + depends on SERIAL_SAMSUNG=y + select SERIAL_CORE_CONSOLE + help + Allow selection of the S3C24XX on-board serial ports for use as + an virtual console. + + Even if you say Y here, the currently visible virtual console + (/dev/tty0) will still be used as the system console by default, but + you can alter that using a kernel command line option such as + "console=ttySACx". (Try "man bootparam" or see the documentation of + your boot loader about how to pass options to the kernel at + boot time.) + +config SERIAL_S3C2400 + tristate "Samsung S3C2410 Serial port support" + depends on ARM && SERIAL_SAMSUNG && CPU_S3C2400 + default y if CPU_S3C2400 + help + Serial port support for the Samsung S3C2400 SoC + +config SERIAL_S3C2410 + tristate "Samsung S3C2410 Serial port support" + depends on SERIAL_SAMSUNG && CPU_S3C2410 + default y if CPU_S3C2410 + help + Serial port support for the Samsung S3C2410 SoC + +config SERIAL_S3C2412 + tristate "Samsung S3C2412/S3C2413 Serial port support" + depends on SERIAL_SAMSUNG && CPU_S3C2412 + default y if CPU_S3C2412 + help + Serial port support for the Samsung S3C2412 and S3C2413 SoC + +config SERIAL_S3C2440 + tristate "Samsung S3C2440/S3C2442 Serial port support" + depends on SERIAL_SAMSUNG && (CPU_S3C2440 || CPU_S3C2442) + default y if CPU_S3C2440 + default y if CPU_S3C2442 + help + Serial port support for the Samsung S3C2440 and S3C2442 SoC + +config SERIAL_S3C24A0 + tristate "Samsung S3C24A0 Serial port support" + depends on SERIAL_SAMSUNG && CPU_S3C24A0 + default y if CPU_S3C24A0 + help + Serial port support for the Samsung S3C24A0 SoC + +config SERIAL_S3C6400 + tristate "Samsung S3C6400/S3C6410 Serial port support" + depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410) + default y + help + Serial port support for the Samsung S3C6400 and S3C6410 + SoCs + +config SERIAL_S5PC100 + tristate "Samsung S5PC100 Serial port support" + depends on SERIAL_SAMSUNG && CPU_S5PC100 + default y + help + Serial port support for the Samsung S5PC100 SoCs + +config SERIAL_MAX3100 + tristate "MAX3100 support" + depends on SPI + select SERIAL_CORE + help + MAX3100 chip support + +config SERIAL_DZ + bool "DECstation DZ serial driver" + depends on MACH_DECSTATION && 32BIT + select SERIAL_CORE + default y + ---help--- + DZ11-family serial controllers for DECstations and VAXstations, + including the DC7085, M7814, and M7819. + +config SERIAL_DZ_CONSOLE + bool "Support console on DECstation DZ serial driver" + depends on SERIAL_DZ=y + select SERIAL_CORE_CONSOLE + default y + ---help--- + If you say Y here, it will be possible to use a serial port as the + system console (the system console is the device which receives all + kernel messages and warnings and which allows logins in single user + mode). + + Note that the firmware uses ttyS3 as the serial console on + DECstations that use this driver. + + If unsure, say Y. + +config SERIAL_ZS + tristate "DECstation Z85C30 serial support" + depends on MACH_DECSTATION + select SERIAL_CORE + default y + ---help--- + Support for the Zilog 85C350 serial communications controller used + for serial ports in newer DECstation systems. These include the + DECsystem 5900 and all models of the DECstation and DECsystem 5000 + systems except from model 200. + + If unsure, say Y. To compile this driver as a module, choose M here: + the module will be called zs. + +config SERIAL_ZS_CONSOLE + bool "Support for console on a DECstation Z85C30 serial port" + depends on SERIAL_ZS=y + select SERIAL_CORE_CONSOLE + default y + ---help--- + If you say Y here, it will be possible to use a serial port as the + system console (the system console is the device which receives all + kernel messages and warnings and which allows logins in single user + mode). + + Note that the firmware uses ttyS1 as the serial console on the + Maxine and ttyS3 on the others using this driver. + + If unsure, say Y. + +config SERIAL_21285 + tristate "DC21285 serial port support" + depends on ARM && FOOTBRIDGE + select SERIAL_CORE + help + If you have a machine based on a 21285 (Footbridge) StrongARM(R)/ + PCI bridge you can enable its onboard serial port by enabling this + option. + +config SERIAL_21285_CONSOLE + bool "Console on DC21285 serial port" + depends on SERIAL_21285=y + select SERIAL_CORE_CONSOLE + help + If you have enabled the serial port on the 21285 footbridge you can + make it the console by answering Y to this option. + + Even if you say Y here, the currently visible virtual console + (/dev/tty0) will still be used as the system console by default, but + you can alter that using a kernel command line option such as + "console=ttyFB". (Try "man bootparam" or see the documentation of + your boot loader (lilo or loadlin) about how to pass options to the + kernel at boot time.) + +config SERIAL_MPSC + bool "Marvell MPSC serial port support" + depends on PPC32 && MV64X60 + select SERIAL_CORE + help + Say Y here if you want to use the Marvell MPSC serial controller. + +config SERIAL_MPSC_CONSOLE + bool "Support for console on Marvell MPSC serial port" + depends on SERIAL_MPSC + select SERIAL_CORE_CONSOLE + help + Say Y here if you want to support a serial console on a Marvell MPSC. + +config SERIAL_PXA + bool "PXA serial port support" + depends on ARCH_PXA || ARCH_MMP + select SERIAL_CORE + help + If you have a machine based on an Intel XScale PXA2xx CPU you + can enable its onboard serial ports by enabling this option. + +config SERIAL_PXA_CONSOLE + bool "Console on PXA serial port" + depends on SERIAL_PXA + select SERIAL_CORE_CONSOLE + help + If you have enabled the serial port on the Intel XScale PXA + CPU you can make it the console by answering Y to this option. + + Even if you say Y here, the currently visible virtual console + (/dev/tty0) will still be used as the system console by default, but + you can alter that using a kernel command line option such as + "console=ttySA0". (Try "man bootparam" or see the documentation of + your boot loader (lilo or loadlin) about how to pass options to the + kernel at boot time.) + +config SERIAL_SA1100 + bool "SA1100 serial port support" + depends on ARM && ARCH_SA1100 + select SERIAL_CORE + help + If you have a machine based on a SA1100/SA1110 StrongARM(R) CPU you + can enable its onboard serial port by enabling this option. + Please read for further + info. + +config SERIAL_SA1100_CONSOLE + bool "Console on SA1100 serial port" + depends on SERIAL_SA1100 + select SERIAL_CORE_CONSOLE + help + If you have enabled the serial port on the SA1100/SA1110 StrongARM + CPU you can make it the console by answering Y to this option. + + Even if you say Y here, the currently visible virtual console + (/dev/tty0) will still be used as the system console by default, but + you can alter that using a kernel command line option such as + "console=ttySA0". (Try "man bootparam" or see the documentation of + your boot loader (lilo or loadlin) about how to pass options to the + kernel at boot time.) + +config SERIAL_BFIN + tristate "Blackfin serial port support" + depends on BLACKFIN + select SERIAL_CORE + select SERIAL_BFIN_UART0 if (BF531 || BF532 || BF533 || BF561) + help + Add support for the built-in UARTs on the Blackfin. + + To compile this driver as a module, choose M here: the + module will be called bfin_5xx. + +config SERIAL_BFIN_CONSOLE + bool "Console on Blackfin serial port" + depends on SERIAL_BFIN=y + select SERIAL_CORE_CONSOLE + +choice + prompt "UART Mode" + depends on SERIAL_BFIN + default SERIAL_BFIN_DMA + help + This driver supports the built-in serial ports of the Blackfin family + of CPUs + +config SERIAL_BFIN_DMA + bool "DMA mode" + depends on !DMA_UNCACHED_NONE && KGDB_SERIAL_CONSOLE=n + help + This driver works under DMA mode. If this option is selected, the + blackfin simple dma driver is also enabled. + +config SERIAL_BFIN_PIO + bool "PIO mode" + help + This driver works under PIO mode. + +endchoice + +config SERIAL_BFIN_UART0 + bool "Enable UART0" + depends on SERIAL_BFIN + help + Enable UART0 + +config BFIN_UART0_CTSRTS + bool "Enable UART0 hardware flow control" + depends on SERIAL_BFIN_UART0 + help + Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS + signal. + +config UART0_CTS_PIN + int "UART0 CTS pin" + depends on BFIN_UART0_CTSRTS && !BF548 + default 23 + help + The default pin is GPIO_GP7. + Refer to arch/blackfin/mach-*/include/mach/gpio.h to see the GPIO map. + +config UART0_RTS_PIN + int "UART0 RTS pin" + depends on BFIN_UART0_CTSRTS && !BF548 + default 22 + help + The default pin is GPIO_GP6. + Refer to arch/blackfin/mach-*/include/mach/gpio.h to see the GPIO map. + +config SERIAL_BFIN_UART1 + bool "Enable UART1" + depends on SERIAL_BFIN && (!BF531 && !BF532 && !BF533 && !BF561) + help + Enable UART1 + +config BFIN_UART1_CTSRTS + bool "Enable UART1 hardware flow control" + depends on SERIAL_BFIN_UART1 + help + Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS + signal. + +config UART1_CTS_PIN + int "UART1 CTS pin" + depends on BFIN_UART1_CTSRTS && !BF548 + default -1 + help + Refer to arch/blackfin/mach-*/include/mach/gpio.h to see the GPIO map. + +config UART1_RTS_PIN + int "UART1 RTS pin" + depends on BFIN_UART1_CTSRTS && !BF548 + default -1 + help + Refer to arch/blackfin/mach-*/include/mach/gpio.h to see the GPIO map. + +config SERIAL_BFIN_UART2 + bool "Enable UART2" + depends on SERIAL_BFIN && (BF54x || BF538 || BF539) + help + Enable UART2 + +config BFIN_UART2_CTSRTS + bool "Enable UART2 hardware flow control" + depends on SERIAL_BFIN_UART2 + help + Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS + signal. + +config UART2_CTS_PIN + int "UART2 CTS pin" + depends on BFIN_UART2_CTSRTS && !BF548 + default -1 + help + Refer to arch/blackfin/mach-*/include/mach/gpio.h to see the GPIO map. + +config UART2_RTS_PIN + int "UART2 RTS pin" + depends on BFIN_UART2_CTSRTS && !BF548 + default -1 + help + Refer to arch/blackfin/mach-*/include/mach/gpio.h to see the GPIO map. + +config SERIAL_BFIN_UART3 + bool "Enable UART3" + depends on SERIAL_BFIN && (BF54x) + help + Enable UART3 + +config BFIN_UART3_CTSRTS + bool "Enable UART3 hardware flow control" + depends on SERIAL_BFIN_UART3 + help + Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS + signal. + +config UART3_CTS_PIN + int "UART3 CTS pin" + depends on BFIN_UART3_CTSRTS && !BF548 + default -1 + help + Refer to arch/blackfin/mach-*/include/mach/gpio.h to see the GPIO map. + +config UART3_RTS_PIN + int "UART3 RTS pin" + depends on BFIN_UART3_CTSRTS && !BF548 + default -1 + help + Refer to arch/blackfin/mach-*/include/mach/gpio.h to see the GPIO map. + +config SERIAL_IMX + bool "IMX serial port support" + depends on ARM && (ARCH_IMX || ARCH_MXC) + select SERIAL_CORE + select RATIONAL + help + If you have a machine based on a Motorola IMX CPU you + can enable its onboard serial port by enabling this option. + +config SERIAL_IMX_CONSOLE + bool "Console on IMX serial port" + depends on SERIAL_IMX + select SERIAL_CORE_CONSOLE + help + If you have enabled the serial port on the Motorola IMX + CPU you can make it the console by answering Y to this option. + + Even if you say Y here, the currently visible virtual console + (/dev/tty0) will still be used as the system console by default, but + you can alter that using a kernel command line option such as + "console=ttySA0". (Try "man bootparam" or see the documentation of + your boot loader (lilo or loadlin) about how to pass options to the + kernel at boot time.) + +config SERIAL_UARTLITE + tristate "Xilinx uartlite serial port support" + depends on PPC32 || MICROBLAZE || MFD_TIMBERDALE + select SERIAL_CORE + help + Say Y here if you want to use the Xilinx uartlite serial controller. + + To compile this driver as a module, choose M here: the + module will be called uartlite. + +config SERIAL_UARTLITE_CONSOLE + bool "Support for console on Xilinx uartlite serial port" + depends on SERIAL_UARTLITE=y + select SERIAL_CORE_CONSOLE + help + Say Y here if you wish to use a Xilinx uartlite as the system + console (the system console is the device which receives all kernel + messages and warnings and which allows logins in single user mode). + +config SERIAL_SUNCORE + bool + depends on SPARC + select SERIAL_CORE + select SERIAL_CORE_CONSOLE + default y + +config SERIAL_SUNZILOG + tristate "Sun Zilog8530 serial support" + depends on SPARC + help + This driver supports the Zilog8530 serial ports found on many Sparc + systems. Say Y or M if you want to be able to these serial ports. + +config SERIAL_SUNZILOG_CONSOLE + bool "Console on Sun Zilog8530 serial port" + depends on SERIAL_SUNZILOG=y + help + If you would like to be able to use the Zilog8530 serial port + on your Sparc system as the console, you can do so by answering + Y to this option. + +config SERIAL_SUNSU + tristate "Sun SU serial support" + depends on SPARC && PCI + help + This driver supports the 8250 serial ports that run the keyboard and + mouse on (PCI) UltraSPARC systems. Say Y or M if you want to be able + to these serial ports. + +config SERIAL_SUNSU_CONSOLE + bool "Console on Sun SU serial port" + depends on SERIAL_SUNSU=y + help + If you would like to be able to use the SU serial port + on your Sparc system as the console, you can do so by answering + Y to this option. + +config SERIAL_MUX + tristate "Serial MUX support" + depends on GSC + select SERIAL_CORE + default y + ---help--- + Saying Y here will enable the hardware MUX serial driver for + the Nova, K class systems and D class with a 'remote control card'. + The hardware MUX is not 8250/16550 compatible therefore the + /dev/ttyB0 device is shared between the Serial MUX and the PDC + software console. The following steps need to be completed to use + the Serial MUX: + + 1. create the device entry (mknod /dev/ttyB0 c 11 0) + 2. Edit the /etc/inittab to start a getty listening on /dev/ttyB0 + 3. Add device ttyB0 to /etc/securetty (if you want to log on as + root on this console.) + 4. Change the kernel command console parameter to: console=ttyB0 + +config SERIAL_MUX_CONSOLE + bool "Support for console on serial MUX" + depends on SERIAL_MUX=y + select SERIAL_CORE_CONSOLE + default y + +config PDC_CONSOLE + bool "PDC software console support" + depends on PARISC && !SERIAL_MUX && VT + default n + help + Saying Y here will enable the software based PDC console to be + used as the system console. This is useful for machines in + which the hardware based console has not been written yet. The + following steps must be competed to use the PDC console: + + 1. create the device entry (mknod /dev/ttyB0 c 11 0) + 2. Edit the /etc/inittab to start a getty listening on /dev/ttyB0 + 3. Add device ttyB0 to /etc/securetty (if you want to log on as + root on this console.) + 4. Change the kernel command console parameter to: console=ttyB0 + +config SERIAL_SUNSAB + tristate "Sun Siemens SAB82532 serial support" + depends on SPARC && PCI + help + This driver supports the Siemens SAB82532 DUSCC serial ports on newer + (PCI) UltraSPARC systems. Say Y or M if you want to be able to these + serial ports. + +config SERIAL_SUNSAB_CONSOLE + bool "Console on Sun Siemens SAB82532 serial port" + depends on SERIAL_SUNSAB=y + help + If you would like to be able to use the SAB82532 serial port + on your Sparc system as the console, you can do so by answering + Y to this option. + +config SERIAL_SUNHV + bool "Sun4v Hypervisor Console support" + depends on SPARC64 + help + This driver supports the console device found on SUN4V Sparc + systems. Say Y if you want to be able to use this device. + +config SERIAL_IP22_ZILOG + tristate "SGI Zilog8530 serial support" + depends on SGI_HAS_ZILOG + select SERIAL_CORE + help + This driver supports the Zilog8530 serial ports found on SGI + systems. Say Y or M if you want to be able to these serial ports. + +config SERIAL_IP22_ZILOG_CONSOLE + bool "Console on SGI Zilog8530 serial port" + depends on SERIAL_IP22_ZILOG=y + select SERIAL_CORE_CONSOLE + +config SERIAL_SH_SCI + tristate "SuperH SCI(F) serial port support" + depends on HAVE_CLK && (SUPERH || H8300) + select SERIAL_CORE + +config SERIAL_SH_SCI_NR_UARTS + int "Maximum number of SCI(F) serial ports" + depends on SERIAL_SH_SCI + default "2" + +config SERIAL_SH_SCI_CONSOLE + bool "Support for console on SuperH SCI(F)" + depends on SERIAL_SH_SCI=y + select SERIAL_CORE_CONSOLE + +config SERIAL_PNX8XXX + bool "Enable PNX8XXX SoCs' UART Support" + depends on MIPS && (SOC_PNX8550 || SOC_PNX833X) + select SERIAL_CORE + help + If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330 + and you want to use serial ports, say Y. Otherwise, say N. + +config SERIAL_PNX8XXX_CONSOLE + bool "Enable PNX8XX0 serial console" + depends on SERIAL_PNX8XXX + select SERIAL_CORE_CONSOLE + help + If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330 + and you want to use serial console, say Y. Otherwise, say N. + +config SERIAL_CORE + tristate + +config SERIAL_CORE_CONSOLE + bool + +config CONSOLE_POLL + bool + +config SERIAL_68328 + bool "68328 serial support" + depends on M68328 || M68EZ328 || M68VZ328 + help + This driver supports the built-in serial port of the Motorola 68328 + (standard, EZ and VZ varieties). + +config SERIAL_68328_RTS_CTS + bool "Support RTS/CTS on 68328 serial port" + depends on SERIAL_68328 + +config SERIAL_MCF + bool "Coldfire serial support" + depends on COLDFIRE + select SERIAL_CORE + help + This serial driver supports the Freescale Coldfire serial ports. + +config SERIAL_MCF_BAUDRATE + int "Default baudrate for Coldfire serial ports" + depends on SERIAL_MCF + default 19200 + help + This setting lets you define what the default baudrate is for the + ColdFire serial ports. The usual default varies from board to board, + and this setting is a way of catering for that. + +config SERIAL_MCF_CONSOLE + bool "Coldfire serial console support" + depends on SERIAL_MCF + select SERIAL_CORE_CONSOLE + help + Enable a ColdFire internal serial port to be the system console. + +config SERIAL_68360_SMC + bool "68360 SMC uart support" + depends on M68360 + help + This driver supports the SMC serial ports of the Motorola 68360 CPU. + +config SERIAL_68360_SCC + bool "68360 SCC uart support" + depends on M68360 + help + This driver supports the SCC serial ports of the Motorola 68360 CPU. + +config SERIAL_68360 + bool + depends on SERIAL_68360_SMC || SERIAL_68360_SCC + default y + +config SERIAL_PMACZILOG + tristate "PowerMac z85c30 ESCC support" + depends on PPC_OF && PPC_PMAC + select SERIAL_CORE + help + This driver supports the Zilog z85C30 serial ports found on + PowerMac machines. + Say Y or M if you want to be able to these serial ports. + +config SERIAL_PMACZILOG_TTYS + bool "Use ttySn device nodes for Zilog z85c30" + depends on SERIAL_PMACZILOG + help + The pmac_zilog driver for the z85C30 chip on many powermacs + historically used the device numbers for /dev/ttySn. The + 8250 serial port driver also uses these numbers, which means + the two drivers being unable to coexist; you could not use + both z85C30 and 8250 type ports at the same time. + + If this option is not selected, the pmac_zilog driver will + use the device numbers allocated for /dev/ttyPZn. This allows + the pmac_zilog and 8250 drivers to co-exist, but may cause + existing userspace setups to break. Programs that need to + access the built-in serial ports on powermacs will need to + be reconfigured to use /dev/ttyPZn instead of /dev/ttySn. + + If you enable this option, any z85c30 ports in the system will + be registered as ttyS0 onwards as in the past, and you will be + unable to use the 8250 module for PCMCIA or other 16C550-style + UARTs. + + Say N unless you need the z85c30 ports on your powermac + to appear as /dev/ttySn. + +config SERIAL_PMACZILOG_CONSOLE + bool "Console on PowerMac z85c30 serial port" + depends on SERIAL_PMACZILOG=y + select SERIAL_CORE_CONSOLE + help + If you would like to be able to use the z85c30 serial port + on your PowerMac as the console, you can do so by answering + Y to this option. + +config SERIAL_LH7A40X + tristate "Sharp LH7A40X embedded UART support" + depends on ARM && ARCH_LH7A40X + select SERIAL_CORE + help + This enables support for the three on-board UARTs of the + Sharp LH7A40X series CPUs. Choose Y or M. + +config SERIAL_LH7A40X_CONSOLE + bool "Support for console on Sharp LH7A40X serial port" + depends on SERIAL_LH7A40X=y + select SERIAL_CORE_CONSOLE + help + Say Y here if you wish to use one of the serial ports as the + system console--the system console is the device which + receives all kernel messages and warnings and which allows + logins in single user mode. + + Even if you say Y here, the currently visible framebuffer console + (/dev/tty0) will still be used as the default system console, but + you can alter that using a kernel command line, for example + "console=ttyAM1". + +config SERIAL_CPM + tristate "CPM SCC/SMC serial port support" + depends on CPM2 || 8xx + select SERIAL_CORE + help + This driver supports the SCC and SMC serial ports on Motorola + embedded PowerPC that contain a CPM1 (8xx) or CPM2 (8xxx) + +config SERIAL_CPM_CONSOLE + bool "Support for console on CPM SCC/SMC serial port" + depends on SERIAL_CPM=y + select SERIAL_CORE_CONSOLE + help + Say Y here if you wish to use a SCC or SMC CPM UART as the system + console (the system console is the device which receives all kernel + messages and warnings and which allows logins in single user mode). + + Even if you say Y here, the currently visible framebuffer console + (/dev/tty0) will still be used as the system console by default, but + you can alter that using a kernel command line option such as + "console=ttyCPM0". (Try "man bootparam" or see the documentation of + your boot loader (lilo or loadlin) about how to pass options to the + kernel at boot time.) + +config SERIAL_SGI_L1_CONSOLE + bool "SGI Altix L1 serial console support" + depends on IA64_GENERIC || IA64_SGI_SN2 + select SERIAL_CORE + select SERIAL_CORE_CONSOLE + help + If you have an SGI Altix and you would like to use the system + controller serial port as your console (you want this!), + say Y. Otherwise, say N. + +config SERIAL_MPC52xx + tristate "Freescale MPC52xx/MPC512x family PSC serial support" + depends on PPC_MPC52xx || PPC_MPC512x + select SERIAL_CORE + help + This driver supports MPC52xx and MPC512x PSC serial ports. If you would + like to use them, you must answer Y or M to this option. Note that + for use as console, it must be included in kernel and not as a + module. + +config SERIAL_MPC52xx_CONSOLE + bool "Console on a Freescale MPC52xx/MPC512x family PSC serial port" + depends on SERIAL_MPC52xx=y + select SERIAL_CORE_CONSOLE + help + Select this options if you'd like to use one of the PSC serial port + of the Freescale MPC52xx family as a console. + +config SERIAL_MPC52xx_CONSOLE_BAUD + int "Freescale MPC52xx/MPC512x family PSC serial port baud" + depends on SERIAL_MPC52xx_CONSOLE=y + default "9600" + help + Select the MPC52xx console baud rate. + This value is only used if the bootloader doesn't pass in the + console baudrate + +config SERIAL_ICOM + tristate "IBM Multiport Serial Adapter" + depends on PCI && (PPC_ISERIES || PPC_PSERIES) + select SERIAL_CORE + select FW_LOADER + help + This driver is for a family of multiport serial adapters + including 2 port RVX, 2 port internal modem, 4 port internal + modem and a split 1 port RVX and 1 port internal modem. + + This driver can also be built as a module. If so, the module + will be called icom. + +config SERIAL_M32R_SIO + bool "M32R SIO I/F" + depends on M32R + default y + select SERIAL_CORE + help + Say Y here if you want to use the M32R serial controller. + +config SERIAL_M32R_SIO_CONSOLE + bool "use SIO console" + depends on SERIAL_M32R_SIO=y + select SERIAL_CORE_CONSOLE + help + Say Y here if you want to support a serial console. + + If you use an M3T-M32700UT or an OPSPUT platform, + please say also y for SERIAL_M32R_PLDSIO. + +config SERIAL_M32R_PLDSIO + bool "M32R SIO I/F on a PLD" + depends on SERIAL_M32R_SIO=y && (PLAT_OPSPUT || PLAT_USRV || PLAT_M32700UT) + default n + help + Say Y here if you want to use the M32R serial controller + on a PLD (Programmable Logic Device). + + If you use an M3T-M32700UT or an OPSPUT platform, + please say Y. + +config SERIAL_TXX9 + bool "TMPTX39XX/49XX SIO support" + depends on HAS_TXX9_SERIAL + select SERIAL_CORE + default y + +config HAS_TXX9_SERIAL + bool + +config SERIAL_TXX9_NR_UARTS + int "Maximum number of TMPTX39XX/49XX SIO ports" + depends on SERIAL_TXX9 + default "6" + +config SERIAL_TXX9_CONSOLE + bool "TMPTX39XX/49XX SIO Console support" + depends on SERIAL_TXX9=y + select SERIAL_CORE_CONSOLE + +config SERIAL_TXX9_STDSERIAL + bool "TX39XX/49XX SIO act as standard serial" + depends on !SERIAL_8250 && SERIAL_TXX9 + +config SERIAL_VR41XX + tristate "NEC VR4100 series Serial Interface Unit support" + depends on CPU_VR41XX + select SERIAL_CORE + help + If you have a NEC VR4100 series processor and you want to use + Serial Interface Unit(SIU) or Debug Serial Interface Unit(DSIU) + (not include VR4111/VR4121 DSIU), say Y. Otherwise, say N. + +config SERIAL_VR41XX_CONSOLE + bool "Enable NEC VR4100 series Serial Interface Unit console" + depends on SERIAL_VR41XX=y + select SERIAL_CORE_CONSOLE + help + If you have a NEC VR4100 series processor and you want to use + a console on a serial port, say Y. Otherwise, say N. + +config SERIAL_JSM + tristate "Digi International NEO PCI Support" + depends on PCI + select SERIAL_CORE + help + This is a driver for Digi International's Neo series + of cards which provide multiple serial ports. You would need + something like this to connect more than two modems to your Linux + box, for instance in order to become a dial-in server. This driver + supports PCI boards only. + + If you have a card like this, say Y here, otherwise say N. + + To compile this driver as a module, choose M here: the + module will be called jsm. + +config SERIAL_SGI_IOC4 + tristate "SGI IOC4 controller serial support" + depends on (IA64_GENERIC || IA64_SGI_SN2) && SGI_IOC4 + select SERIAL_CORE + help + If you have an SGI Altix with an IOC4 based Base IO card + and wish to use the serial ports on this card, say Y. + Otherwise, say N. + +config SERIAL_SGI_IOC3 + tristate "SGI Altix IOC3 serial support" + depends on (IA64_GENERIC || IA64_SGI_SN2) && SGI_IOC3 + select SERIAL_CORE + help + If you have an SGI Altix with an IOC3 serial card, + say Y or M. Otherwise, say N. + +config SERIAL_MSM + bool "MSM on-chip serial port support" + depends on ARM && ARCH_MSM + select SERIAL_CORE + +config SERIAL_MSM_CONSOLE + bool "MSM serial console support" + depends on SERIAL_MSM=y + select SERIAL_CORE_CONSOLE + +config SERIAL_NETX + tristate "NetX serial port support" + depends on ARM && ARCH_NETX + select SERIAL_CORE + help + If you have a machine based on a Hilscher NetX SoC you + can enable its onboard serial port by enabling this option. + + To compile this driver as a module, choose M here: the + module will be called netx-serial. + +config SERIAL_NETX_CONSOLE + bool "Console on NetX serial port" + depends on SERIAL_NETX=y + select SERIAL_CORE_CONSOLE + help + If you have enabled the serial port on the Hilscher NetX SoC + you can make it the console by answering Y to this option. + +config SERIAL_OF_PLATFORM + tristate "Serial port on Open Firmware platform bus" + depends on PPC_OF || MICROBLAZE + depends on SERIAL_8250 || SERIAL_OF_PLATFORM_NWPSERIAL + help + If you have a PowerPC based system that has serial ports + on a platform specific bus, you should enable this option. + Currently, only 8250 compatible ports are supported, but + others can easily be added. + +config SERIAL_OF_PLATFORM_NWPSERIAL + tristate "NWP serial port driver" + depends on PPC_OF && PPC_DCR + select SERIAL_OF_PLATFORM + select SERIAL_CORE_CONSOLE + select SERIAL_CORE + help + This driver supports the cell network processor nwp serial + device. + +config SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE + bool "Console on NWP serial port" + depends on SERIAL_OF_PLATFORM_NWPSERIAL=y + select SERIAL_CORE_CONSOLE + help + Support for Console on the NWP serial ports. + +config SERIAL_QE + tristate "Freescale QUICC Engine serial port support" + depends on QUICC_ENGINE + select SERIAL_CORE + select FW_LOADER + default n + help + This driver supports the QE serial ports on Freescale embedded + PowerPC that contain a QUICC Engine. + +config SERIAL_SC26XX + tristate "SC2681/SC2692 serial port support" + depends on SNI_RM + select SERIAL_CORE + help + This is a driver for the onboard serial ports of + older RM400 machines. + +config SERIAL_SC26XX_CONSOLE + bool "Console on SC2681/SC2692 serial port" + depends on SERIAL_SC26XX + select SERIAL_CORE_CONSOLE + help + Support for Console on SC2681/SC2692 serial ports. + +config SERIAL_BFIN_SPORT + tristate "Blackfin SPORT emulate UART (EXPERIMENTAL)" + depends on BLACKFIN && EXPERIMENTAL + select SERIAL_CORE + help + Enable SPORT emulate UART on Blackfin series. + + To compile this driver as a module, choose M here: the + module will be called bfin_sport_uart. + +choice + prompt "Baud rate for Blackfin SPORT UART" + depends on SERIAL_BFIN_SPORT + default SERIAL_SPORT_BAUD_RATE_57600 + help + Choose a baud rate for the SPORT UART, other uart settings are + 8 bit, 1 stop bit, no parity, no flow control. + +config SERIAL_SPORT_BAUD_RATE_115200 + bool "115200" + +config SERIAL_SPORT_BAUD_RATE_57600 + bool "57600" + +config SERIAL_SPORT_BAUD_RATE_38400 + bool "38400" + +config SERIAL_SPORT_BAUD_RATE_19200 + bool "19200" + +config SERIAL_SPORT_BAUD_RATE_9600 + bool "9600" +endchoice + +config SPORT_BAUD_RATE + int + depends on SERIAL_BFIN_SPORT + default 115200 if (SERIAL_SPORT_BAUD_RATE_115200) + default 57600 if (SERIAL_SPORT_BAUD_RATE_57600) + default 38400 if (SERIAL_SPORT_BAUD_RATE_38400) + default 19200 if (SERIAL_SPORT_BAUD_RATE_19200) + default 9600 if (SERIAL_SPORT_BAUD_RATE_9600) + +config SERIAL_TIMBERDALE + tristate "Support for timberdale UART" + depends on MFD_TIMBERDALE + select SERIAL_CORE + ---help--- + Add support for UART controller on timberdale. + +config SERIAL_BCM63XX + tristate "bcm63xx serial port support" + select SERIAL_CORE + depends on BCM63XX + help + If you have a bcm63xx CPU, you can enable its onboard + serial port by enabling this options. + + To compile this driver as a module, choose M here: the + module will be called bcm963xx_uart. + +config SERIAL_BCM63XX_CONSOLE + bool "Console on bcm63xx serial port" + depends on SERIAL_BCM63XX=y + select SERIAL_CORE_CONSOLE + help + If you have enabled the serial port on the bcm63xx CPU + you can make it the console by answering Y to this option. + +config SERIAL_GRLIB_GAISLER_APBUART + tristate "GRLIB APBUART serial support" + depends on OF + ---help--- + Add support for the GRLIB APBUART serial port. + +config SERIAL_GRLIB_GAISLER_APBUART_CONSOLE + bool "Console on GRLIB APBUART serial port" + depends on SERIAL_GRLIB_GAISLER_APBUART=y + select SERIAL_CORE_CONSOLE + help + Support for running a console on the GRLIB APBUART + +endmenu diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/linux/drivers/serial/Makefile posixrdp/posixxrdp.orig/linux/drivers/serial/Makefile --- xrdp/xrdp-0.5.0~20100303cvs.orig/linux/drivers/serial/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/linux/drivers/serial/Makefile 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,87 @@ +# +# Makefile for the kernel serial device drivers. +# + +obj-$(CONFIG_SERIAL_CORE) += serial_core.o +obj-$(CONFIG_SERIAL_21285) += 21285.o + +# These Sparc drivers have to appear before others such as 8250 +# which share ttySx minor node space. Otherwise console device +# names change and other unplesantries. +obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o +obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o +obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o +obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o +obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o + +obj-$(CONFIG_SERIAL_8250) += 8250.o +obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o +obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o +obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o +obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o +obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o +obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o +obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o +obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o +obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o +obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o +obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o +obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o +obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o +obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o +obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o +obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o +obj-$(CONFIG_SERIAL_PXA) += pxa.o +obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o +obj-$(CONFIG_SERIAL_SA1100) += sa1100.o +obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o +obj-$(CONFIG_SERIAL_BFIN) += bfin_5xx.o +obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o +obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o +obj-$(CONFIG_SERIAL_S3C2400) += s3c2400.o +obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o +obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o +obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o +obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o +obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o +obj-$(CONFIG_SERIAL_S5PC100) += s3c6400.o +obj-$(CONFIG_SERIAL_MAX3100) += max3100.o +obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o +obj-$(CONFIG_SERIAL_MUX) += mux.o +obj-$(CONFIG_SERIAL_68328) += 68328serial.o +obj-$(CONFIG_SERIAL_68360) += 68360serial.o +obj-$(CONFIG_SERIAL_MCF) += mcf.o +obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o +obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o +obj-$(CONFIG_SERIAL_DZ) += dz.o +obj-$(CONFIG_SERIAL_ZS) += zs.o +obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o +obj-$(CONFIG_SERIAL_SGI_L1_CONSOLE) += sn_console.o +obj-$(CONFIG_SERIAL_CPM) += cpm_uart/ +obj-$(CONFIG_SERIAL_IMX) += imx.o +obj-$(CONFIG_SERIAL_MPC52xx) += mpc52xx_uart.o +obj-$(CONFIG_SERIAL_ICOM) += icom.o +obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o +obj-$(CONFIG_SERIAL_MPSC) += mpsc.o +obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o +obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o +obj-$(CONFIG_SERIAL_SC26XX) += sc26xx.o +obj-$(CONFIG_SERIAL_JSM) += jsm/ +obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o +obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o +obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o +obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o +obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o +obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o +obj-$(CONFIG_SERIAL_MSM) += msm_serial.o +obj-$(CONFIG_SERIAL_NETX) += netx-serial.o +obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o +obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o +obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o +obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o +obj-$(CONFIG_SERIAL_QE) += ucc_uart.o +obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o +obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o +obj-$(CONFIG_SERIAL_RDPUART) += rdptty.o + +rdptty-objs := rdp.o rdpmain.o diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/linux/drivers/serial/ntddser.h posixrdp/posixxrdp.orig/linux/drivers/serial/ntddser.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/linux/drivers/serial/ntddser.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/linux/drivers/serial/ntddser.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,404 @@ +/* + * DDK definitions for serial port + * + * Copyright (C) 2006 Eric Pouech + * From w32api package + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef _NTDDSER_H_ +#define _NTDDSER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define IOCTL_SERIAL_CLEAR_STATS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 36, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_CLR_DTR \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 10, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_CLR_RTS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 13, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_CONFIG_SIZE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 32, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_BAUD_RATE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 20, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_CHARS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 22, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_COMMSTATUS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 27, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_DTRRTS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 30, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_HANDFLOW \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 24, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_LINE_CONTROL \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 21, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_MODEM_CONTROL \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 37, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_MODEMSTATUS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 26, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_PROPERTIES \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 29, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_STATS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 35, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_TIMEOUTS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 8, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_WAIT_MASK \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 16, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_IMMEDIATE_CHAR \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 6, METHOD_BUFFERED, FILE_ANY_ACCESS) +#ifndef IOCTL_SERIAL_LSRMST_INSERT +/* it's already defined in winioctl.h */ +#define IOCTL_SERIAL_LSRMST_INSERT \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 31, METHOD_BUFFERED, FILE_ANY_ACCESS) +#endif +#define IOCTL_SERIAL_PURGE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 19, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_RESET_DEVICE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 11, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_BAUD_RATE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 1, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_BREAK_ON \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 4, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_BREAK_OFF \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 5, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_CHARS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 23, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_DTR \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 9, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_FIFO_CONTROL \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 39, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_HANDFLOW \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 25, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_LINE_CONTROL \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 3, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_MODEM_CONTROL \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 38, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_QUEUE_SIZE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 2, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_RTS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 12, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_TIMEOUTS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 7, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_WAIT_MASK \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 17, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_XOFF \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 14, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_XON \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 15, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_WAIT_ON_MASK \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 18, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_XOFF_COUNTER \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 28, METHOD_BUFFERED, FILE_ANY_ACCESS) + +typedef unsigned long ULONG; +typedef long LONG; +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef short SHORT; +typedef unsigned short WCHAR; +typedef UCHAR BOOLEAN; + +typedef struct _SERIAL_BAUD_RATE { + ULONG BaudRate; +} SERIAL_BAUD_RATE, *PSERIAL_BAUD_RATE; + +/* SERIAL_BAUD_RATE.BaudRate constants */ +#define SERIAL_BAUD_075 0x00000001 +#define SERIAL_BAUD_110 0x00000002 +#define SERIAL_BAUD_134_5 0x00000004 +#define SERIAL_BAUD_150 0x00000008 +#define SERIAL_BAUD_300 0x00000010 +#define SERIAL_BAUD_600 0x00000020 +#define SERIAL_BAUD_1200 0x00000040 +#define SERIAL_BAUD_1800 0x00000080 +#define SERIAL_BAUD_2400 0x00000100 +#define SERIAL_BAUD_4800 0x00000200 +#define SERIAL_BAUD_7200 0x00000400 +#define SERIAL_BAUD_9600 0x00000800 +#define SERIAL_BAUD_14400 0x00001000 +#define SERIAL_BAUD_19200 0x00002000 +#define SERIAL_BAUD_38400 0x00004000 +#define SERIAL_BAUD_56K 0x00008000 +#define SERIAL_BAUD_128K 0x00010000 +#define SERIAL_BAUD_115200 0x00020000 +#define SERIAL_BAUD_57600 0x00040000 +#define SERIAL_BAUD_USER 0x10000000 + +typedef struct _SERIAL_CHARS +{ + UCHAR EofChar; + UCHAR ErrorChar; + UCHAR BreakChar; + UCHAR EventChar; + UCHAR XonChar; + UCHAR XoffChar; +} SERIAL_CHARS, *PSERIAL_CHARS; + +typedef struct _SERIAL_STATUS +{ + ULONG Errors; + ULONG HoldReasons; + ULONG AmountInInQueue; + ULONG AmountInOutQueue; + UCHAR EofReceived; + UCHAR WaitForImmediate; +} SERIAL_STATUS, *PSERIAL_STATUS; + +typedef struct _SERIAL_HANDFLOW +{ + ULONG ControlHandShake; + ULONG FlowReplace; + LONG XonLimit; + LONG XoffLimit; +} SERIAL_HANDFLOW, *PSERIAL_HANDFLOW; + +#define SERIAL_DTR_MASK 0x00000003 +#define SERIAL_DTR_CONTROL 0x00000001 +#define SERIAL_DTR_HANDSHAKE 0x00000002 +#define SERIAL_CTS_HANDSHAKE 0x00000008 +#define SERIAL_DSR_HANDSHAKE 0x00000010 +#define SERIAL_DCD_HANDSHAKE 0x00000020 +#define SERIAL_OUT_HANDSHAKEMASK 0x00000038 +#define SERIAL_DSR_SENSITIVITY 0x00000040 +#define SERIAL_ERROR_ABORT 0x80000000 +#define SERIAL_CONTROL_INVALID 0x7fffff84 +#define SERIAL_AUTO_TRANSMIT 0x00000001 +#define SERIAL_AUTO_RECEIVE 0x00000002 +#define SERIAL_ERROR_CHAR 0x00000004 +#define SERIAL_NULL_STRIPPING 0x00000008 +#define SERIAL_BREAK_CHAR 0x00000010 +#define SERIAL_RTS_MASK 0x000000c0 +#define SERIAL_RTS_CONTROL 0x00000040 +#define SERIAL_RTS_HANDSHAKE 0x00000080 +#define SERIAL_TRANSMIT_TOGGLE 0x000000c0 +#define SERIAL_XOFF_CONTINUE 0x80000000 +#define SERIAL_FLOW_INVALID 0x7fffff20 + +typedef struct _SERIAL_LINE_CONTROL { + UCHAR StopBits; + UCHAR Parity; + UCHAR WordLength; +} SERIAL_LINE_CONTROL, *PSERIAL_LINE_CONTROL; + +/* SERIAL_LINE_CONTROL.StopBits constants */ +#define STOP_BIT_1 0x00 +#define STOP_BITS_1_5 0x01 +#define STOP_BITS_2 0x02 + +/* SERIAL_LINE_CONTROL.Parity constants */ +#define NO_PARITY 0x00 +#define ODD_PARITY 0x01 +#define EVEN_PARITY 0x02 +#define MARK_PARITY 0x03 +#define SPACE_PARITY 0x04 + +/* IOCTL_SERIAL_(GET_MODEM_CONTROL, SET_MODEM_CONTROL) flags */ +#define SERIAL_IOC_MCR_DTR 0x00000001 +#define SERIAL_IOC_MCR_RTS 0x00000002 +#define SERIAL_IOC_MCR_OUT1 0x00000004 +#define SERIAL_IOC_MCR_OUT2 0x00000008 +#define SERIAL_IOC_MCR_LOOP 0x00000010 + +typedef struct _SERIAL_COMMPROP +{ + USHORT PacketLength; + USHORT PacketVersion; + ULONG ServiceMask; + ULONG Reserved1; + ULONG MaxTxQueue; + ULONG MaxRxQueue; + ULONG MaxBaud; + ULONG ProvSubType; + ULONG ProvCapabilities; + ULONG SettableParams; + ULONG SettableBaud; + USHORT SettableData; + USHORT SettableStopParity; + ULONG CurrentTxQueue; + ULONG CurrentRxQueue; + ULONG ProvSpec1; + ULONG ProvSpec2; + WCHAR ProvChar[1]; +} SERIAL_COMMPROP, *PSERIAL_COMMPROP; + +/* SERIAL_COMMPROP.SettableParams flags */ +#define SERIAL_SP_PARITY 0x0001 +#define SERIAL_SP_BAUD 0x0002 +#define SERIAL_SP_DATABITS 0x0004 +#define SERIAL_SP_STOPBITS 0x0008 +#define SERIAL_SP_HANDSHAKING 0x0010 +#define SERIAL_SP_PARITY_CHECK 0x0020 +#define SERIAL_SP_CARRIER_DETECT 0x0040 + +/* SERIAL_COMMPROP.ProvCapabilities flags */ +#define SERIAL_PCF_DTRDSR 0x00000001 +#define SERIAL_PCF_RTSCTS 0x00000002 +#define SERIAL_PCF_CD 0x00000004 +#define SERIAL_PCF_PARITY_CHECK 0x00000008 +#define SERIAL_PCF_XONXOFF 0x00000010 +#define SERIAL_PCF_SETXCHAR 0x00000020 +#define SERIAL_PCF_TOTALTIMEOUTS 0x00000040 +#define SERIAL_PCF_INTTIMEOUTS 0x00000080 +#define SERIAL_PCF_SPECIALCHARS 0x00000100 +#define SERIAL_PCF_16BITMODE 0x00000200 + +/* SERIAL_COMMPROP.SettableData flags */ +#define SERIAL_DATABITS_5 0x0001 +#define SERIAL_DATABITS_6 0x0002 +#define SERIAL_DATABITS_7 0x0004 +#define SERIAL_DATABITS_8 0x0008 +#define SERIAL_DATABITS_16 0x0010 +#define SERIAL_DATABITS_16X 0x0020 + +/* SERIAL_COMMPROP.SettableStopParity flags */ +#define SERIAL_STOPBITS_10 0x0001 +#define SERIAL_STOPBITS_15 0x0002 +#define SERIAL_STOPBITS_20 0x0004 +#define SERIAL_PARITY_NONE 0x0100 +#define SERIAL_PARITY_ODD 0x0200 +#define SERIAL_PARITY_EVEN 0x0400 +#define SERIAL_PARITY_MARK 0x0800 +#define SERIAL_PARITY_SPACE 0x1000 + +typedef struct _SERIALPERF_STATS +{ + ULONG ReceivedCount; + ULONG TransmittedCount; + ULONG FrameErrorCount; + ULONG SerialOverrunErrorCount; + ULONG BufferOverrunErrorCount; + ULONG ParityErrorCount; +} SERIALPERF_STATS, *PSERIALPERF_STATS; + +typedef struct _SERIAL_TIMEOUTS +{ + ULONG ReadIntervalTimeout; + ULONG ReadTotalTimeoutMultiplier; + ULONG ReadTotalTimeoutConstant; + ULONG WriteTotalTimeoutMultiplier; + ULONG WriteTotalTimeoutConstant; +} SERIAL_TIMEOUTS, *PSERIAL_TIMEOUTS; + +/* IOCTL_SERIAL_(GET_WAIT_MASK, SET_WAIT_MASK, WAIT_ON_MASK) flags */ +#define SERIAL_EV_RXCHAR 0x0001 +#define SERIAL_EV_RXFLAG 0x0002 +#define SERIAL_EV_TXEMPTY 0x0004 +#define SERIAL_EV_CTS 0x0008 +#define SERIAL_EV_DSR 0x0010 +#define SERIAL_EV_RLSD 0x0020 +#define SERIAL_EV_BREAK 0x0040 +#define SERIAL_EV_ERR 0x0080 +#define SERIAL_EV_RING 0x0100 +#define SERIAL_EV_PERR 0x0200 +#define SERIAL_EV_RX80FULL 0x0400 +#define SERIAL_EV_EVENT1 0x0800 +#define SERIAL_EV_EVENT2 0x1000 + +/* IOCTL_SERIAL_LSRMST_INSERT constants */ +#define SERIAL_LSRMST_LSR_DATA 0x01 +#define SERIAL_LSRMST_LSR_NODATA 0x02 +#define SERIAL_LSRMST_MST 0x03 +#define SERIAL_LSRMST_ESCAPE 0x00 + +/* IOCTL_SERIAL_PURGE constants */ +#define SERIAL_PURGE_TXABORT 0x00000001 +#define SERIAL_PURGE_RXABORT 0x00000002 +#define SERIAL_PURGE_TXCLEAR 0x00000004 +#define SERIAL_PURGE_RXCLEAR 0x00000008 + +/* IOCTL_SERIAL_SET_FIFO_CONTROL constants */ +#define SERIAL_IOC_FCR_FIFO_ENABLE 0x00000001 +#define SERIAL_IOC_FCR_RCVR_RESET 0x00000002 +#define SERIAL_IOC_FCR_XMIT_RESET 0x00000004 +#define SERIAL_IOC_FCR_DMA_MODE 0x00000008 +#define SERIAL_IOC_FCR_RES1 0x00000010 +#define SERIAL_IOC_FCR_RES2 0x00000020 +#define SERIAL_IOC_FCR_RCVR_TRIGGER_LSB 0x00000040 +#define SERIAL_IOC_FCR_RCVR_TRIGGER_MSB 0x00000080 + +typedef struct _SERIAL_QUEUE_SIZE +{ + ULONG InSize; + ULONG OutSize; +} SERIAL_QUEUE_SIZE, *PSERIAL_QUEUE_SIZE; + +typedef struct _SERIAL_XOFF_COUNTER +{ + ULONG Timeout; + LONG Counter; + UCHAR XoffChar; +} SERIAL_XOFF_COUNTER, *PSERIAL_XOFF_COUNTER; + +typedef struct _SERIAL_BASIC_SETTINGS +{ + SERIAL_TIMEOUTS Timeouts; + SERIAL_HANDFLOW HandFlow; + ULONG RxFifo; + ULONG TxFifo; +} SERIAL_BASIC_SETTINGS, *PSERIAL_BASIC_SETTINGS; + +#define SERIAL_ERROR_BREAK 0x00000001 +#define SERIAL_ERROR_FRAMING 0x00000002 +#define SERIAL_ERROR_OVERRUN 0x00000004 +#define SERIAL_ERROR_QUEUEOVERRUN 0x00000008 +#define SERIAL_ERROR_PARITY 0x00000010 + +#define SERIAL_SP_UNSPECIFIED 0x00000000 +#define SERIAL_SP_RS232 0x00000001 +#define SERIAL_SP_PARALLEL 0x00000002 +#define SERIAL_SP_RS422 0x00000003 +#define SERIAL_SP_RS423 0x00000004 +#define SERIAL_SP_RS449 0x00000005 +#define SERIAL_SP_MODEM 0X00000006 +#define SERIAL_SP_FAX 0x00000021 +#define SERIAL_SP_SCANNER 0x00000022 +#define SERIAL_SP_BRIDGE 0x00000100 +#define SERIAL_SP_LAT 0x00000101 +#define SERIAL_SP_TELNET 0x00000102 +#define SERIAL_SP_X25 0x00000103 +#define SERIAL_SP_SERIALCOMM 0x00000001 + +#define SERIAL_TX_WAITING_FOR_CTS 0x00000001 +#define SERIAL_TX_WAITING_FOR_DSR 0x00000002 +#define SERIAL_TX_WAITING_FOR_DCD 0x00000004 +#define SERIAL_TX_WAITING_FOR_XON 0x00000008 +#define SERIAL_TX_WAITING_XOFF_SENT 0x00000010 +#define SERIAL_TX_WAITING_ON_BREAK 0x00000020 +#define SERIAL_RX_WAITING_FOR_DSR 0x00000040 + +#define SERIAL_DTR_STATE 0x00000001 +#define SERIAL_RTS_STATE 0x00000002 +#define SERIAL_CTS_STATE 0x00000010 +#define SERIAL_DSR_STATE 0x00000020 +#define SERIAL_RI_STATE 0x00000040 +#define SERIAL_DCD_STATE 0x00000080 + +typedef struct _SERIALCONFIG +{ + ULONG Size; + USHORT Version; + ULONG SubType; + ULONG ProvOffset; + ULONG ProviderSize; + WCHAR ProviderData[1]; +} SERIALCONFIG,*PSERIALCONFIG; + +#ifdef __cplusplus +} +#endif + +#endif /* _NTDDSER_H_ */ diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/linux/drivers/serial/rdp.c posixrdp/posixxrdp.orig/linux/drivers/serial/rdp.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/linux/drivers/serial/rdp.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/linux/drivers/serial/rdp.c 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,1622 @@ +#include +#include + +static struct rdp_tty * g_tty_driver = (struct rdp_tty *)NULL; +static DEFINE_MUTEX(g_tty_driver_mutex); + +static struct mutex * p_tty_mutex = (struct mutex *)NULL; +static struct rdp_port g_ports[MAX_PORT]; +static int g_port_count = 0; + +static struct mutex g_write_mutex = {}; +static struct mutex * p_write_mutex = (struct mutex *)NULL; + +static struct rdp_cmd * g_cmds[16]; +static struct rdp_cmd * g_pend[16]; +static struct rdp_irq_entry * g_read[16]; +static struct rdp_write_entry * g_write[16]; +static completed_cmd_list_t * g_compl[16]; +static struct rdp_cb_entry * g_cb[16]; +static int g_initialized = 0; + +static int rdp_receive(struct rdp_port *, int, int *, char *); +static void __cb_enq(struct rdp_cb_entry *); +static void cb_enq(struct rdp_cb_entry *); +static struct rdp_cb_entry * __cb_deq(struct rdp_cb_entry **); +static struct rdp_cb_entry * cb_deq(struct rdp_cb_entry **); +static void read_enq(struct rdp_irq_entry *); +static struct rdp_irq_entry * read_deq(struct rdp_irq_entry **); +static void write_enq(struct rdp_write_entry *); +static struct rdp_write_entry * write_deq(struct rdp_write_entry **); +static struct list_head * compl_enq(completed_cmd_list_t *); +static completed_cmd_list_t * __compl_deq(completed_cmd_list_t **); +static completed_cmd_list_t * compl_deq(completed_cmd_list_t **); + +#define Q_NAME "rdp_workq" +static void rdp_cmdw_handler(struct work_struct *); +static struct workqueue_struct * g_cmdq = (struct workqueue_struct *)NULL; +static DECLARE_WORK(g_cmdw, rdp_cmdw_handler); + +#define COMPLQ_NAME "rdp_compq" +static void rdp_complw_handler(struct work_struct *); +static struct workqueue_struct * g_complq = (struct workqueue_struct *)NULL; +//static DECLARE_DELAYED_WORK(g_complw, rdp_complw_handler); +static DECLARE_WORK(g_complw, rdp_complw_handler); + +#define READQ_NAME "rdp_readq" +static void rdp_readw_handler(struct work_struct *); +static struct workqueue_struct * g_readq = (struct workqueue_struct *)NULL; +static DECLARE_WORK(g_readw, rdp_readw_handler); + +#define WRITEQ_NAME "rdp_writeq" +static void rdp_writew_handler(struct work_struct *); +static struct workqueue_struct * g_writeq = (struct workqueue_struct *)NULL; +static DECLARE_WORK(g_writew, rdp_writew_handler); + +static struct list_head * p_enq(struct rdp_cmd *); + +static const char * cmdarray[] = CMD_TO_STRING_ARRAY_DEF; + +static LIST_HEAD(rdp_completed_cmds); +static DEFINE_SPINLOCK(rdp_completed_cmds_lock); + +static LIST_HEAD(rdp_read_list); +static DEFINE_SPINLOCK(rdp_read_lock); +static LIST_HEAD(rdp_write_list); +static DEFINE_SPINLOCK(rdp_write_lock); + +static DEFINE_MUTEX(g_cb_mutex); +static struct mutex * p_cb_mutex = (struct mutex *)NULL; + + +/*** + *** Netlink Connection ("cn") functions + ***/ + +static struct rdp_family rdp_default_family = {}; + +static DEFINE_SPINLOCK(rdp_flock); +static DEFINE_SPINLOCK(rdp_cmd_lock); +static LIST_HEAD(rdp_families); +static LIST_HEAD(rdp_outbound_cmd_list); +static LIST_HEAD(rdp_pending_cmd_list); + +#define CBQ_NAME "rdp_cbq" +static void rdp_cn_callback_bh(CBARGS); +static LIST_HEAD(rdp_cb_list); +static DEFINE_SPINLOCK(rdp_cb_lock); +static void rdp_cbw_handler(struct work_struct *); +static struct workqueue_struct * g_cbq = (struct workqueue_struct *)NULL; +static DECLARE_WORK(g_cbw, rdp_cbw_handler); + + +static void rdp_cn_callback(CBARGS) { + struct rdp_cb_entry * cb_entry = (struct rdp_cb_entry *)NULL; + unsigned char * buf = (unsigned char *)NULL; + unsigned char * sbuf = (unsigned char *)NULL; + struct cn_msg * lmsg = (struct cn_msg *)NULL; + + if (imsg == NULL || g_initialized < 1) { + goto end; + } + cb_entry = (struct rdp_cb_entry *)kzalloc((sizeof(struct rdp_cb_entry) + imsg->len + 1), GFP_ATOMIC); + if (cb_entry == NULL) { + goto end; + } + else { + if (parms != NULL) { + memcpy(&(cb_entry->parms), parms, sizeof(struct netlink_skb_parms)); + } + lmsg = &(cb_entry->imsg); + buf = (unsigned char *)(lmsg + 1); + sbuf = (unsigned char *)(imsg + 1); +// memcpy(&(cb_entry->imsg), imsg, (sizeof(struct cn_msg) + imsg->len)); + memcpy(lmsg, imsg, sizeof(struct cn_msg)); + memcpy(buf, sbuf, imsg->len); + } + + cb_enq(cb_entry); + queue_work(g_cbq, &g_cbw); + + end:; +} + +static void rdp_cbw_handler(struct work_struct * work) { + struct rdp_cb_entry * cb = (struct rdp_cb_entry *)NULL; + + if (work == NULL || g_initialized < 1 || p_cb_mutex == NULL) { + goto end; + } + mutex_lock(p_cb_mutex); + cb_deq(&cb); + if (cb != NULL) { + rdp_cn_callback_bh(&(cb->imsg), &(cb->parms)); + } + mutex_unlock(p_cb_mutex); + + end:; +} + +static void rdp_cn_callback_bh(CBARGS) { + unsigned long flags; + int found = 0; + int mlen = 0; + int i = 0; + int lcompleted = 0; + uint8_t mtype = 0x00; + int status = 0; + struct cn_msg * msg = (struct cn_msg *)imsg; + rdp_netlink_msg * m = (rdp_netlink_msg *)(msg + 1); + struct device * gdev = (struct device *)NULL; + if (msg == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: msg is a null pointer", __func__); + goto end; + } + mutex_lock(&(g_tty_driver_mutex)); + if (g_tty_driver != NULL) { + //smp_rmb(); + status = atomic_read(&(g_tty_driver->status)); + } + else { + status = RDP_STATUS_EXIT; + } + if (g_tty_driver == NULL || status != RDP_STATUS_NORMAL) { + } + else if (msg != NULL) { + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + while (msg->len) { + rdp_reg_num id; + struct rdp_cmd * cmd = (struct rdp_cmd *)NULL; + memcpy(&id, m->id.id, sizeof(rdp_reg_num)); + mtype |= m->type; + mlen = m->len; + if (msg->ack > 0 && mtype < 0x81) { + spin_lock_irqsave(&rdp_cmd_lock, flags); + for (i = 0; i < 16; i++) { + cmd = g_pend[i]; + if (cmd != NULL) { + DBGLOG(KERN_INFO "INFO\t[%s()]: cmd->seqid = %d", __func__, cmd->seqid); + //smp_rmb(); + lcompleted = atomic_read(&(cmd->completed)); + if (cmd->seqid == msg->seq && lcompleted < 1) { + smp_mb__before_atomic_inc(); + atomic_inc(&(cmd->completed)); + found = 1; + g_pend[i] = NULL; + break; + } + } + } + spin_unlock_irqrestore(&rdp_cmd_lock, flags); + if (likely(found > 0 && cmd != NULL)) { + completed_cmd_list_t * cmd_item = (completed_cmd_list_t *)NULL; + DBGLOG(KERN_INFO "INFO\t[%s()]: cmd found, queueing callback...", __func__); + if (cmd != NULL && cmd->aux != NULL) { + cmd_item = (completed_cmd_list_t *)(cmd->aux); + cmd->aux = (void *)NULL; + } + else { + cmd_item = (completed_cmd_list_t *)kzalloc(sizeof(completed_cmd_list_t), GFP_KERNEL); + } + cmd_item->cmd = cmd; + if (cmd != NULL && cmd->odata != NULL && cmd->olen > 0 && m->data != NULL && mlen > 0 && cmd->odata != m->data && cmd->olen == mlen) { + memcpy(cmd->odata, m->data, MINVAL(cmd->olen, mlen)); + DBGLOG(KERN_INFO "INFO\t[%s()]: cmd->odata = %p; cmd->olen = %d; m->data = %p; m->len = %d", __func__, cmd->odata, cmd->olen, m->data, m->len); + } + compl_enq(cmd_item); + queue_work(g_complq, &g_complw); + } + else { + //DBGLOG(KERN_INFO "INFO\t[%s()]: cmd not found! (%d)", __func__, msg->seq); + } + } + else if (mtype > 0 && m != NULL) { + /* if an unsolicited cn packet is received, then it should be handled as a + * "virtual interrupt" received from the userspace daemon; so, queue up an + * ersatz irq handler: + */ + struct rdp_irq_data * irq_data = (struct rdp_irq_data *)(m->data); + struct rdp_irq_entry * irq_entry = (struct rdp_irq_entry *)NULL; + DBGLOG(KERN_INFO "INFO\t[%s()]: (IRQ)", __func__); + mtype &= ~RDP_ASYNC; + switch (mtype) { + case RDP_ADDPORT: + { + int i = 0; + DBGLOG(KERN_INFO "INFO\t[%s()]: calling tty_register_device()", __func__); + if (p_tty_mutex != NULL) { + mutex_lock(p_tty_mutex); + } + i = g_port_count; + if (!(gdev = tty_register_device((struct tty_driver *)(g_tty_driver->driver), i, NULL))) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: tty_register_device() failed", __func__); + } + else if (g_ports[i].initialized > 0) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: port is already initialized", __func__); + } + else { + DBGLOG(KERN_INFO "INFO\t[%s()]: tty_register_device() was successful", __func__); + memset(&(g_ports[i]), 0, sizeof(struct rdp_port)); + mutex_init(&(g_ports[i].mut)); + mutex_lock(&(g_ports[i].mut)); + g_ports[i].initialized = 1; + g_ports[i].g_ports_index = i; + spin_lock_init(&(g_ports[i].cmd_lock)); + spin_lock_init(&(g_ports[i].status_lock)); + //smp_wmb(); + atomic_set(&(g_ports[i].open_count), 0); + g_ports[i].rec.port = &(g_ports[i]); + g_ports[i].rec.tty = g_ports[i].item; + g_ports[i].rec.initialized = 1; + g_ports[i].rec.owner = THIS_MODULE; + if (g_tty_driver != NULL && g_tty_driver->driver != NULL && g_tty_driver->driver->name != NULL) { + scnprintf(g_ports[i].rec.name, RDP_MAXNAMELEN, "%s%d", g_tty_driver->driver->name, i); + } + spin_lock_init(&(g_ports[i].rec.lock)); + mutex_unlock(&(g_ports[i].mut)); + g_port_count++; + } + if (p_tty_mutex != NULL) { + mutex_unlock(p_tty_mutex); + } + } + break; + case RDP_RXFULL: + { + int idx = 0; + int found = 0; + const int nr = MAX_PORT; + if (p_tty_mutex != NULL) { + mutex_lock(p_tty_mutex); + } + for (idx = 0; idx < nr; idx++) { + if (g_ports[idx].device_id == irq_data->device_id) { + found = 1; + break; + } + } + irq_entry = (struct rdp_irq_entry *)kzalloc(sizeof(struct rdp_irq_entry), GFP_KERNEL); + if (irq_entry != NULL) { + irq_entry->data = irq_data; + if (found > 0) { + irq_entry->port = &(g_ports[idx]); + } + else { + irq_entry->port = &(g_ports[0]); + } + read_enq(irq_entry); + queue_work(g_readq, &g_readw); + } + if (p_tty_mutex != NULL) { + mutex_unlock(p_tty_mutex); + } + } + break; + default: + { + DBGLOG(KERN_WARNING "WARNING\t[%s()]: INTERRUPT --> unrecognized opcode (\"0x%02x\")", __func__, mtype); + } + break; + } + } + msg->len -= (sizeof(rdp_netlink_msg) + m->len); + m = (rdp_netlink_msg *)(((u8 *)m) + m->len); + } + } + mutex_unlock(&(g_tty_driver_mutex)); + + end:; + DBGLOG(KERN_INFO "INFO\t[%s()]: done.", __func__); +} + + +static int rdp_netlink_send(struct rdp_record * dev, rdp_netlink_msg * msg, int seq, int memmode) { + unsigned long flags; + int rv = 0; + char buf[512]; + struct cn_msg * m = (struct cn_msg *)buf; + rdp_netlink_msg * w = (rdp_netlink_msg *)(m+1); + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + if (dev == NULL) { + DBGLOG(KERN_WARNING "WARNING\t[%s()]: dev is a null pointer", __func__); + rv = -EINVAL; + goto end; + } + if (msg == NULL) { + DBGLOG(KERN_WARNING "WARNING\t[%s()]: msg is a null pointer", __func__); + rv = -EINVAL; + goto end; + } + memset(buf, 0, sizeof(buf)); + m->id.idx = CN_IDX_RDP; + m->id.val = CN_VAL_RDP; + spin_lock_irqsave(&(dev->lock), flags); + m->seq = seq; + spin_unlock_irqrestore(&(dev->lock), flags); + rv = m->seq; + m->len = sizeof(rdp_netlink_msg) + msg->len; + DBGLOG(KERN_INFO "INFO\t[%s()]: about to call memcpy()...", __func__); + memcpy(w, msg, m->len); + DBGLOG(KERN_INFO "INFO\t[%s()]: about to call cn_netlink_send()... {m->len = \"%d\"}", __func__, m->len); + cn_netlink_send(m, 0, memmode); + end: + DBGLOG(KERN_INFO "INFO\t[%s()]: done (rv = \"%d\").", __func__, rv); + return rv; +} + +static int rdp_init_netlink(void) { + int rv = 0; + struct cb_id rdp_id = { + .idx = CN_IDX_RDP, + .val = CN_VAL_RDP, + }; + spin_lock_init(&(rdp_default_family.lock)); + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + rv = cn_add_callback(&rdp_id, "rdp", &rdp_cn_callback); + DBGLOG(KERN_INFO "INFO\t[%s()]: done.", __func__); + return rv; +} + +static void rdp_stop_netlink(void) { + struct cb_id rdp_id = { + .idx = CN_IDX_RDP, + .val = CN_VAL_RDP, + }; + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + cn_del_callback(&rdp_id); + DBGLOG(KERN_INFO "INFO\t[%s()]: done.", __func__); +} + +int rdp_register_family(struct rdp_family * newf) { + unsigned long flags; + struct list_head * ent = (struct list_head *)NULL; + struct list_head * n = (struct list_head *)NULL; + struct rdp_family * f = (struct rdp_family *)NULL; + int ret = 0; + + spin_lock_irqsave(&rdp_flock, flags); + list_for_each_safe(ent, n, &rdp_families) { + f = list_entry(ent, struct rdp_family, family_entry); + if (f->fid == newf->fid) { + ret = -EEXIST; + break; + } + } + + if (!ret) { + //smp_wmb(); + atomic_set(&newf->refcnt, 0); + newf->need_exit = 0; + list_add_tail(&newf->family_entry, &rdp_families); + } + spin_unlock_irqrestore(&rdp_flock, flags); + + return ret; +} + +void rdp_unregister_family(struct rdp_family * fent) { + unsigned long flags; + struct list_head * ent = (struct list_head *)NULL; + struct list_head * n = (struct list_head *)NULL; + struct rdp_family * f = (struct rdp_family *)NULL; + int refcnt = 0; + + spin_lock_irqsave(&rdp_flock, flags); + list_for_each_safe(ent, n, &rdp_families) { + f = list_entry(ent, struct rdp_family, family_entry); + if (f->fid == fent->fid) { + list_del(&fent->family_entry); + break; + } + } + + fent->need_exit = 1; + + spin_unlock_irqrestore(&rdp_flock, flags); + + //smp_rmb(); + refcnt = atomic_read(&(fent->refcnt)); + while (refcnt) { + printk(KERN_INFO "Waiting for family %u to become free: refcnt=%d.\n", fent->fid, atomic_read(&fent->refcnt)); + if (msleep_interruptible(1000)) { + flush_signals(current); + } + //smp_rmb(); + refcnt = atomic_read(&(fent->refcnt)); + } +} + +/* + * Should be called under rdp_flock held. + */ +struct rdp_family * rdp_family_registered(u8 fid) { + struct list_head * ent = (struct list_head *)NULL; + struct list_head * n = (struct list_head *)NULL; + struct rdp_family * f = (struct rdp_family *)NULL; + int ret = 0; + list_for_each_safe(ent, n, &rdp_families) { + f = list_entry(ent, struct rdp_family, family_entry); + if (f->fid == fid) { + ret = 1; + break; + } + } + return (ret) ? f : NULL; +} + +static void __rdp_family_put(struct rdp_family * f) { + int tmp = 0; + smp_mb__before_atomic_dec(); + tmp = atomic_dec_and_test(&f->refcnt); + if (tmp) { + f->need_exit = 1; + } +} + +void rdp_family_put(struct rdp_family * f) { + spin_lock(&rdp_flock); + __rdp_family_put(f); + spin_unlock(&rdp_flock); +} + +static void __rdp_family_get(struct rdp_family *f) { + smp_mb__before_atomic_inc(); + atomic_inc(&(f->refcnt)); +} + +void rdp_family_get(struct rdp_family *f) { + spin_lock(&rdp_flock); + __rdp_family_get(f); + spin_unlock(&rdp_flock); +} + +/*****/ +/*****/ + +static int cmd_output(struct rdp_cmd * rcmd, int memmode) { + unsigned long flags; + int rv = 0; + struct rdp_record * rec = (struct rdp_record *)NULL; + struct rdp_family * f = (struct rdp_family *)NULL; + unsigned char * cbuf = (unsigned char *)NULL; + void * data = (void *)NULL; + int len = 0; + rdp_netlink_msg msg; + unsigned char cmd = 0x00; + struct rdp_port * port = (struct rdp_port *)NULL; + struct tty_struct * tty = (struct tty_struct *)NULL; + int ilen = 0; + int olen = 0; + void * idata = (void *)NULL; + void * odata = (void *)NULL; + uint32_t cmd_idx = 0x00000000; + + if (rcmd == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: rcmd is a NULL pointer", __func__); + rv = -EINVAL; + goto end; + } + else { + port = rcmd->port; + cmd = rcmd->cmd; + tty = rcmd->tty; + ilen = rcmd->ilen; + olen = rcmd->olen; + idata = rcmd->idata; + odata = rcmd->odata; + len = ilen; + data = idata; + cmd_idx = rcmd->cmd_idx; + } + if (ilen > 0 && idata == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: idata is a NULL pointer", __func__); + rv = -EINVAL; + goto end; + } + if (olen > 0 && odata == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: odata is a NULL pointer", __func__); + rv = -ENOMEM; + goto end; + } + if (cmd == RDP_PING || cmd > RDP_XCHAR) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: opcode not implemented (\"%8.8x\")", __func__, cmd); + rv = -EINVAL; + goto end; + } + + DBGLOG(KERN_INFO "INFO\t[%s()]: called (cmd = \"%s\", %d)", __func__, RDPCMD(cmd), cmd); + + rec = &(rcmd->port->rec); + + memset(&msg, 0, sizeof(rdp_netlink_msg)); + //smp_wmb(); + atomic_set(&(rec->refcnt), 0); + INIT_COMPLETION(rec->released); + + spin_lock_irqsave(&rdp_flock, flags); + f = &rdp_default_family; + __rdp_family_get(f); + rec->family = f; + spin_unlock_irqrestore(&rdp_flock, flags); + + msg.type = cmd; + + if (len > 0 && data != NULL) { + msg.len = len + sizeof(uint32_t); + cbuf = (unsigned char *)kzalloc((sizeof(rdp_netlink_msg) + len), memmode); + if (cbuf == NULL) { + rv = -ENOMEM; + goto end; + } + else { + rdp_netlink_msg * pm = (rdp_netlink_msg *)cbuf; + uint32_t * pn = (uint32_t *)(pm+1); + unsigned char * pd = (unsigned char *)(pn+1); + memcpy(pm, &msg, sizeof(rdp_netlink_msg)); + memcpy(pn, &cmd_idx, sizeof(uint32_t)); + memcpy(pd, data, len); + } + } + else { + cbuf = (unsigned char *)kzalloc((sizeof(rdp_netlink_msg) + sizeof(uint32_t)), memmode); + if (cbuf == NULL) { + rv = -ENOMEM; + goto end; + } + else { + rdp_netlink_msg * pm = (rdp_netlink_msg *)cbuf; + uint32_t * pn = (uint32_t *)(pm+1); + memcpy(pm, &msg, sizeof(rdp_netlink_msg)); + memcpy(pn, &cmd_idx, sizeof(uint32_t)); + } + } + INIT_LIST_HEAD(&(rcmd->list)); + rcmd->seqid = rec->seq++; + p_enq(rcmd); + DBGLOG(KERN_INFO "INFO\t[%s()]: about to call rdp_netlink_send()...", __func__); + rv = rdp_netlink_send(rec, (void *)cbuf, rcmd->seqid, memmode); + DBGLOG(KERN_INFO "INFO\t[%s()]: (\" returned)", __func__); + + if (cbuf != NULL) { + kfree(cbuf); + } + + end: + DBGLOG(KERN_INFO "INFO\t[%s()]: done (rv = \"%d\")", __func__, rv); + return rv; +} + + +static struct list_head * __compl_enq(completed_cmd_list_t * cmd_item) { + struct list_head * rv = (struct list_head *)NULL; + int found = 0; + int i = 0; + + if (cmd_item != NULL) { + for (i = 0; i < 16; i++) { + if (g_compl[i] == NULL) { + found = 1; + break; + } + } + if (found) { + g_compl[i] = cmd_item; + } + else { + rv = NULL; + } + } + + return rv; +} + +static struct list_head * compl_enq(completed_cmd_list_t * cmd_item) { + unsigned long flags; + struct list_head * rv = (struct list_head *)NULL; + + spin_lock_irqsave(&rdp_completed_cmds_lock, flags); + if (likely(cmd_item != NULL)) { + rv = __compl_enq(cmd_item); + } + spin_unlock_irqrestore(&rdp_completed_cmds_lock, flags); + + return rv; +} + +static completed_cmd_list_t * __compl_deq(completed_cmd_list_t ** rcmd) { + completed_cmd_list_t * rv = (completed_cmd_list_t *)NULL; + int i = 0; + + for (i = 0; i < 16; i++) { + if (g_compl[i] != NULL) { + rv = g_compl[i]; + g_compl[i] = (completed_cmd_list_t *)NULL; + break; + } + } + + /* + if (list_empty(&rdp_completed_cmds)) { + rv = (completed_cmd_list_t *)NULL; + } + else { + rv = list_entry(rdp_completed_cmds.next, completed_cmd_list_t, list); + } + if (rv != NULL) { + list_del_init(&(rv->list)); + } + */ + + if (rcmd != NULL) { + *rcmd = rv; + } + + return rv; +} + +static completed_cmd_list_t * compl_deq(completed_cmd_list_t ** rcmd) { + unsigned long flags; + completed_cmd_list_t * rv = (completed_cmd_list_t *)NULL; + + spin_lock_irqsave(&rdp_completed_cmds_lock, flags); + rv = __compl_deq(rcmd); + spin_unlock_irqrestore(&rdp_completed_cmds_lock, flags); + + return rv; +} + + +static struct list_head * cmd_enq(struct rdp_cmd * rcmd) { + unsigned long flags; + int i = 0; + int found = 0; + struct list_head * rv = &rdp_outbound_cmd_list; + + if (rcmd != NULL) { + spin_lock_irqsave(&rdp_cmd_lock, flags); + for (i = 0; i < 16; i++) { + if (g_cmds[i] == NULL) { + found = 1; + break; + } + } + if (found) { + g_cmds[i] = rcmd; + } + else { + rv = NULL; + } + spin_unlock_irqrestore(&rdp_cmd_lock, flags); + } + + return rv; +} + +static struct rdp_cmd * cmd_deq(struct rdp_cmd ** rcmd) { + unsigned long flags; + int i = 0; + struct rdp_cmd * rv = (struct rdp_cmd *)NULL; + + spin_lock_irqsave(&rdp_cmd_lock, flags); + for (i = 0; i < 16; i++) { + if (g_cmds[i] != NULL) { + rv = g_cmds[i]; + g_cmds[i] = (struct rdp_cmd *)NULL; + break; + } + } + spin_unlock_irqrestore(&rdp_cmd_lock, flags); + + if (rcmd != NULL) { + *rcmd = rv; + } + + return rv; +} + +static void read_enq(struct rdp_irq_entry * irq_entry) { + unsigned long flags; + int found = 0; + int i = 0; + + if (irq_entry != NULL) { + spin_lock_irqsave(&rdp_read_lock, flags); + for (i = 0; i < 16; i++) { + if (g_read[i] == NULL) { + found = 1; + break; + } + } + if (found) { + g_read[i] = irq_entry; + } + else { + //rv = NULL; + } + spin_unlock_irqrestore(&rdp_read_lock, flags); + } + + + /* + if (irq_entry != NULL) { + INIT_LIST_HEAD(&(irq_entry->list)); + spin_lock_irqsave(&rdp_read_lock, flags); + list_add_tail(&(irq_entry->list), &rdp_read_list); + spin_unlock_irqrestore(&rdp_read_lock, flags); + } + */ +} + +static struct rdp_irq_entry * read_deq(struct rdp_irq_entry ** itm) { + unsigned long flags; + struct rdp_irq_entry * rv = (struct rdp_irq_entry *)NULL; + int i = 0; + + spin_lock_irqsave(&rdp_read_lock, flags); + for (i = 0; i < 16; i++) { + if (g_read[i] != NULL) { + rv = g_read[i]; + g_read[i] = (struct rdp_irq_entry *)NULL; + break; + } + } + spin_unlock_irqrestore(&rdp_read_lock, flags); + + /* + spin_lock_irqsave(&rdp_read_lock, flags); + rv = list_entry(rdp_read_list.next, struct rdp_irq_entry, list); + if (rv != NULL) { + list_del_init(&(rv->list)); + } + spin_unlock_irqrestore(&rdp_read_lock, flags); + */ + + if (itm != NULL) { + *itm = rv; + } + + return rv; +} + +static void write_enq(struct rdp_write_entry * write_entry) { + unsigned long flags; + int found = 0; + int i = 0; + + if (write_entry != NULL) { + spin_lock_irqsave(&rdp_write_lock, flags); + for (i = 0; i < 16; i++) { + if (g_write[i] == NULL) { + found = 1; + break; + } + } + if (found) { + g_write[i] = write_entry; + } + else { + //rv = NULL; + } + spin_unlock_irqrestore(&rdp_write_lock, flags); + } + + /* + if (write_entry != NULL) { + INIT_LIST_HEAD(&(write_entry->list)); + spin_lock_irqsave(&rdp_write_lock, flags); + list_add_tail(&(write_entry->list), &rdp_write_list); + spin_unlock_irqrestore(&rdp_write_lock, flags); + } + */ +} + +static struct rdp_write_entry * write_deq(struct rdp_write_entry ** itm) { + unsigned long flags; + struct rdp_write_entry * rv = (struct rdp_write_entry *)NULL; + int i = 0; + + spin_lock_irqsave(&rdp_write_lock, flags); + for (i = 0; i < 16; i++) { + if (g_write[i] != NULL) { + rv = g_write[i]; + g_write[i] = (struct rdp_write_entry *)NULL; + break; + } + } + spin_unlock_irqrestore(&rdp_write_lock, flags); + + /* + spin_lock_irqsave(&rdp_write_lock, flags); + rv = list_entry(rdp_write_list.next, struct rdp_write_entry, list); + if (rv != NULL) { + list_del_init(&(rv->list)); + } + spin_unlock_irqrestore(&rdp_write_lock, flags); + */ + + if (itm != NULL) { + *itm = rv; + } + + return rv; +} + +static void __cb_enq(struct rdp_cb_entry * cb_entry) { + int found = 0; + int i = 0; + + if (cb_entry != NULL) { + for (i = 0; i < 16; i++) { + if (g_cb[i] == NULL) { + found = 1; + break; + } + } + if (found) { + g_cb[i] = cb_entry; + } + else { + //rv = NULL; + } + } + + /* + if (cb_entry != NULL) { + INIT_LIST_HEAD(&(cb_entry->list)); + spin_lock_irqsave(&rdp_cb_lock, flags); + list_add_tail(&(cb_entry->list), &rdp_cb_list); + spin_unlock_irqrestore(&rdp_cb_lock, flags); + } + */ +} + +static void cb_enq(struct rdp_cb_entry * cb_entry) { + unsigned long flags; + + spin_lock_irqsave(&rdp_cb_lock, flags); + __cb_enq(cb_entry); + spin_unlock_irqrestore(&rdp_cb_lock, flags); +} + + +static struct rdp_cb_entry * __cb_deq(struct rdp_cb_entry ** itm) { + struct rdp_cb_entry * rv = (struct rdp_cb_entry *)NULL; + int i = 0; + + for (i = 0; i < 16; i++) { + if (g_cb[i] != NULL) { + rv = g_cb[i]; + g_cb[i] = (struct rdp_cb_entry *)NULL; + break; + } + } + + /* + rv = list_entry(rdp_cb_list.next, struct rdp_cb_entry, list); + if (rv != NULL) { + list_del_init(&(rv->list)); + } + */ + + if (itm != NULL) { + *itm = rv; + } + + return rv; +} + +static struct rdp_cb_entry * cb_deq(struct rdp_cb_entry ** itm) { + unsigned long flags; + struct rdp_cb_entry * rv = (struct rdp_cb_entry *)NULL; + + spin_lock_irqsave(&rdp_cb_lock, flags); + __cb_deq(&rv); + if (itm != NULL) { + *itm = rv; + } + spin_unlock_irqrestore(&rdp_cb_lock, flags); + + return rv; +} + + +static struct list_head * p_enq(struct rdp_cmd * rcmd) { + unsigned long flags; + int i = 0; + int found = 0; + struct list_head * rv = &rdp_outbound_cmd_list; + + if (rcmd != NULL) { + + spin_lock_irqsave(&rdp_cmd_lock, flags); + + for (i = 0; i < 16; i++) { + if (g_pend[i] == NULL) { + found = 1; + break; + } + } + + if (found) { + g_pend[i] = rcmd; + } + else { + rv = NULL; + } + + spin_unlock_irqrestore(&rdp_cmd_lock, flags); + } + + return rv; +} + +#ifdef DO_PDEQ + +static struct rdp_cmd * p_deq(struct rdp_cmd ** rcmd) { + unsigned long flags; + int i = 0; + struct rdp_cmd * rv = (struct rdp_cmd *)NULL; + + spin_lock_irqsave(&rdp_cmd_lock, flags); + for (i = 0; i < 16; i++) { + if (g_pend[i] != NULL) { + rv = g_pend[i]; + g_pend[i] = (struct rdp_cmd *)NULL; + break; + } + } + spin_unlock_irqrestore(&rdp_cmd_lock, flags); + + if (rcmd != NULL) { + *rcmd = rv; + } + + return rv; +} + +#endif + + +static int cmd_process_list(struct list_head * cmdlist) { + int rv = 0; + struct rdp_cmd * cmd = (struct rdp_cmd *)NULL; + + might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + + if (g_tty_driver != NULL) { + do { + cmd_deq(&cmd); + if (cmd != NULL) { + DBGLOG(KERN_INFO "INFO\t[%s()]: outputting RDP command", __func__); +// cmd_output(cmd, GFP_ATOMIC); + cmd_output(cmd, GFP_KERNEL); + } + } while (cmd != NULL); + } + + DBGLOG(KERN_INFO "INFO\t[%s()]: done.", __func__); + + return rv; +} + +static struct rdp_cmd * cmd_send(struct rdp_port * port, unsigned char cmd, void * idata, int ilen, void * odata, int olen, int memmode) { + int seqid = 0; + int cmd_idx = 0; + struct rdp_cmd * lcmd = (struct rdp_cmd *)NULL; + + DBGLOG(KERN_INFO "INFO\t[%s()]: called (cmd = \"%s\", ilen = \"%d\", olen = \"%d\")", __func__, RDPCMD(cmd), ilen, olen); + + if (port == NULL) { + goto end; + } + + lcmd = (struct rdp_cmd *)kzalloc(sizeof(struct rdp_cmd), memmode); + + if (lcmd == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: lcmd == NULL", __func__); + goto end; + } + + spin_lock_init(&(lcmd->lock)); + lcmd->cmd = cmd; + lcmd->port = port; + lcmd->idata = idata; + lcmd->ilen = ilen; + lcmd->odata = odata; + lcmd->olen = olen; + lcmd->cmd_idx = cmd_idx; + lcmd->aux = (void *)kzalloc(sizeof(completed_cmd_list_t), memmode); + //smp_wmb(); + atomic_set(&(lcmd->completed), 0); + + if (olen > 0 && lcmd->odata == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: lcmd->odata == NULL", __func__); + goto end; + } + + DBGLOG(KERN_INFO "INFO\t[%s()]: about to call cmd_enq()...", __func__); + cmd_enq(lcmd); + DBGLOG(KERN_INFO "INFO\t[%s()]: cmd_enq() returned", __func__); + + end:; + DBGLOG(KERN_INFO "INFO\t[%s()]: done (lcmd = \"%p\", seqid = \"%d\").", __func__, lcmd, seqid); + return lcmd; +} + + +static int __cmd_exec(struct rdp_port * port, unsigned char cmd, void * idata, int ilen, void * odata, int olen, int memmode) { + unsigned long flags; + int rv = 0; + int seqid = 0; + int lcompleted = 0x00000000; + int cnt = 0; + const unsigned int max_timeout = 2000; /* in jiffies: 1 jiffy = 0.004 sec */ + struct rdp_cmd * lcmd = (struct rdp_cmd *)NULL; + DECLARE_COMPLETION_ONSTACK(tdone); + struct completion * ldone = (struct completion *)NULL; + //struct work_struct * lwork = (struct work_struct *)NULL; + //DECLARE_WORK(g_cmdw, rdp_cmdw_handler); + struct work_struct twork; + struct work_struct * lwork = &twork; + + DBGLOG(KERN_INFO "INFO\t[%s()]: called (cmd = \"%s\", ilen = \"%d\", olen = \"%d\")", __func__, RDPCMD(cmd), ilen, olen); + + if (port == NULL) { + rv = -EINVAL; + goto end; + } + +// ldone = (struct completion *)kzalloc(sizeof(struct completion), memmode); + ldone = &tdone; + if (ldone == NULL) { + rv = -ENOMEM; + goto end; + } + else { +// init_completion(ldone); + } + + DBGLOG(KERN_INFO "INFO\t[%s()]: about to call cmd_send()...", __func__); + lcmd = cmd_send(port, cmd, idata, ilen, odata, olen, memmode); + DBGLOG(KERN_INFO "INFO\t[%s()]: cmd_send() returned", __func__); + if (lcmd == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: \"lcmd\" is a NULL pointer", __func__); + goto end; + } + lcmd->done = ldone; + DBGLOG(KERN_INFO "INFO\t[%s()]: queue_delayed_work() returned", __func__); + +// lwork = (struct work_struct *)kzalloc(sizeof(struct work_struct), memmode); + if (lwork == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: \"lwork\" is a NULL pointer", __func__); + goto end; + } +// INIT_WORK(lwork, rdp_cmdw_handler); + INIT_WORK_ON_STACK(lwork, rdp_cmdw_handler); + + do { + DBGLOG(KERN_INFO "INFO\t[%s()]: waiting for completion... (%d)", __func__, cnt); +// queue_work(g_cmdq, &g_cmdw); + queue_work(g_cmdq, lwork); + wait_for_completion_interruptible_timeout(ldone, max_timeout); + flush_workqueue(g_cmdq); +// spin_lock_irqsave(&(lcmd->lock), flags); +// INIT_COMPLETION(*ldone); + INIT_COMPLETION(tdone); + //smp_rmb(); + lcompleted = atomic_read(&(lcmd->completed)); +// spin_unlock_irqrestore(&(lcmd->lock), flags); + cnt++; + } while (!(lcompleted) && cnt < 5); + if (!lcompleted) { + int i = 0; + spin_lock_irqsave(&rdp_cmd_lock, flags); + for (i = 0; i < 16; i++) { + if (g_cmds[i] == lcmd) { + g_cmds[i] = (struct rdp_cmd *)NULL; + kfree(lcmd); + lcmd = (struct rdp_cmd *)NULL; + } + } + spin_unlock_irqrestore(&rdp_cmd_lock, flags); + } + DBGLOG(KERN_INFO "INFO\t[%s()]: (\" completed)", __func__); + if (lwork != NULL) { + //kfree(lwork); + } + + if (lcmd != NULL && lcmd->olen > 0 && lcmd->odata != NULL && olen > 0 && odata != NULL && odata != lcmd->odata) { + memcpy(odata, lcmd->odata, MINVAL(lcmd->olen,olen)); + } + if (lcmd != NULL) { + memset(lcmd, 0, sizeof(struct rdp_cmd)); + kfree(lcmd); + } + + end:; + DBGLOG(KERN_INFO "INFO\t[%s()]: done (rv = \"%d\", seqid = \"%d\").", __func__, rv, seqid); + return rv; +} + +static int cmd_exec(struct rdp_port * port, unsigned char cmd, void * idata, int ilen, void * odata, int olen) { + might_sleep(); + return __cmd_exec(port, cmd, idata, ilen, odata, olen, GFP_KERNEL); +} + + +#define DO_RECEIVE 1 +#ifdef DO_RECEIVE + +static int rdp_receive(struct rdp_port * port, int stat, int * ibuflen, char * buf) { + int rv = 1; + int buflen = 0; + unsigned char ch = 0; + struct tty_struct * tty = port->item; + + if (ibuflen != NULL) { + buflen = *ibuflen; + } + + DBGLOG(KERN_INFO "INFO\t[%s()]: called (stat = \"%d\", buflen = \"%d\")", __func__, stat, buflen); + + if (port == NULL || tty == NULL) { + rv = -EINVAL; + goto end; + } + + if (buflen == 1 && buf != NULL) { + ch = buf[0]; + tty_insert_flip_char(tty, ch, 0); + } + else if (buflen > 1 && buf != NULL) { + tty_insert_flip_string(tty, buf, buflen); + } + + if (buflen > 0) { + tty_flip_buffer_push(tty); + } + + + end: + return rv; +} + +#endif + + +static int supp_write(struct tty_struct * tty, const unsigned char * buffer, int count) { + unsigned long flags; + int rv = 0; + int cnt = 0; + int done = 0; + struct rdp_port * port = (struct rdp_port *)NULL; + struct work_struct * lwork = (struct work_struct *)NULL; + const unsigned int max_timeout = 2000; /* in jiffies: 1 jiffy = 0.004 sec */ + +// might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + + if (tty != NULL && tty->index > -1 && tty->index < MAX_PORT) { + port = &(g_ports[tty->index]); + } + if (port == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: tty->index out of range", __func__); + rv = -ENOMEM; + goto end; + } + else if (port->initialized < 1 || atomic_read(&(port->open_count)) < 1) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: port is not open", __func__); + rv = -EACCES; + goto end; + } + else { + struct rdp_write_entry * write_entry = (struct rdp_write_entry *)NULL; + + if (p_write_mutex != NULL) { +// mutex_lock(p_write_mutex); + } + +// write_entry = (struct rdp_write_entry *)kzalloc(sizeof(struct rdp_write_entry), GFP_ATOMIC); + write_entry = (struct rdp_write_entry *)kzalloc(sizeof(struct rdp_write_entry), GFP_KERNEL); + spin_lock_init(&(write_entry->lock)); +// spin_lock_irqsave(&(write_entry->lock), flags); + write_entry->port = port; + write_entry->len = count; + write_entry->data = (unsigned char *)buffer; + write_entry->rv = 0; + write_entry->completed = 0; + init_completion(&(write_entry->done)); + + write_enq(write_entry); +// spin_unlock_irqrestore(&(write_entry->lock), flags); + //spin_lock_irqsave(&rdp_write_lock, flags); + //queue_work(g_writeq, &g_writew); + //spin_unlock_irqrestore(&rdp_write_lock, flags); + do { + lwork = (struct work_struct *)kzalloc(sizeof(struct work_struct), GFP_KERNEL); + INIT_WORK(lwork, rdp_writew_handler); + DBGLOG(KERN_INFO "INFO\t[%s()]: waiting for completion... (%d)", __func__, cnt); + queue_work(g_writeq, lwork); +// wait_for_completion_interruptible_timeout(&(write_entry->done), max_timeout); +// wait_for_completion_timeout(&(write_entry->done), max_timeout); +// flush_workqueue(g_writeq); + spin_lock_irqsave(&(write_entry->lock), flags); + if (write_entry->completed > 0) { + done = 1; + kfree(lwork); + lwork = (struct work_struct *)NULL; + } + else { + done = 0; + write_entry->canceled = 1; + } +// INIT_COMPLETION(write_entry->done); + spin_unlock_irqrestore(&(write_entry->lock), flags); + cnt++; + } while (!done && cnt < 3); + + if (p_write_mutex != NULL) { +// mutex_unlock(p_write_mutex); + } + + rv = count; + } + + end:; + return rv; +} + +static int supp_open(struct tty_struct * tty, struct file * file) { + int rv = 0; + uint32_t fd = 0; + int oc = 0; + struct rdp_port * port = (struct rdp_port *)NULL; + + might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + + if (likely(tty != NULL && tty->index > -1 && tty->index < MAX_PORT)) { + port = &(g_ports[tty->index]); + } + if (unlikely(port == NULL)) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: tty->index out of range", __func__); + rv = -ENOMEM; + goto end; + } + else { + + if (likely(port->initialized == 1 && port->item == NULL)) { + port->item = tty; + port->rec.tty = port->item; + port->rec.port = port; + port->fp = file; + } + + //smp_rmb(); + oc = atomic_read(&(port->open_count)); + cmd_exec(port, RDP_OPEN, NULL, 0, &fd, sizeof(fd)); + DBGLOG(KERN_INFO "INFO\t[%s()]: fd = %d", __func__, fd); + rv = fd; + if (oc == 0) { + cmd_exec(port, RDP_START, NULL, 0, NULL, 0); + } + smp_mb__before_atomic_inc(); + atomic_inc(&(port->open_count)); + + } + + end:; + DBGLOG(KERN_INFO "INFO\t[%s()]: done.", __func__); + return rv; +} + +static void supp_close(struct tty_struct * tty, struct file * file) { + int oc = 0; + struct rdp_port * port = (struct rdp_port *)NULL; + + might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + + if (likely(tty != NULL && tty->index > -1 && tty->index < MAX_PORT && g_ports[tty->index].initialized > 0)) { + port = &(g_ports[tty->index]); + } + if (unlikely(port == NULL || port->item == NULL || port->initialized < 1)) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: port or port->item is NULL or not initialized", __func__); + } + else { + //smp_rmb(); + oc = atomic_read(&(port->open_count)); + if (oc == 1) { + cmd_exec(port, RDP_STOP, NULL, 0, NULL, 0); + } + cmd_exec(port, RDP_CLOSE, NULL, 0, NULL, 0); + smp_mb__before_atomic_dec(); + atomic_dec(&(port->open_count)); + } +} + +int __init rdp_ops_setup(struct tty_operations * ops) { + int rv = 0; + + if (ops == NULL) { + rv = -EINVAL; + goto exit; + } + ops->open = supp_open; + ops->close = supp_close; + ops->write = supp_write; + + exit:; + return rv; +} + +int __init rdp_init(struct tty_driver * drv, struct mutex * tty_mutex) { + int rv = 0; + + might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + + //mutex_lock(&(g_tty_driver_mutex)); + + if (p_tty_mutex == NULL) { + p_tty_mutex = tty_mutex; + } + p_write_mutex = &g_write_mutex; + memset(p_write_mutex, 0x00, sizeof(struct mutex)); + //mutex_init(p_write_mutex); + + memset(g_ports, 0, sizeof(g_ports)); + memset(g_cmds, 0, sizeof(g_cmds)); + memset(g_pend, 0, sizeof(g_pend)); + memset(g_read, 0, sizeof(g_read)); + memset(g_write, 0, sizeof(g_write)); + memset(g_compl, 0, sizeof(g_compl)); + memset(g_cb, 0, sizeof(g_cb)); + + g_tty_driver = (struct rdp_tty *)kzalloc(sizeof(struct rdp_tty), GFP_KERNEL); + //mutex_init(&(g_tty_driver_mutex)); + //mutex_lock(&(g_tty_driver_mutex)); + g_tty_driver->driver = drv; + if (p_cb_mutex == NULL) { + memset(&g_cb_mutex, 0x00, sizeof(struct mutex)); + p_cb_mutex = &g_cb_mutex; + } + //mutex_init(p_cb_mutex); + //mutex_lock(p_cb_mutex); + //smp_wmb(); + atomic_set(&(g_tty_driver->status), RDP_STATUS_LOADING); + g_cbq = create_singlethread_workqueue(CBQ_NAME); + g_cmdq = create_singlethread_workqueue(Q_NAME); + g_complq = create_singlethread_workqueue(COMPLQ_NAME); + g_readq = create_singlethread_workqueue(READQ_NAME); + g_writeq = create_singlethread_workqueue(WRITEQ_NAME); + //smp_wmb(); + atomic_set(&(g_tty_driver->status), RDP_STATUS_NORMAL); + g_initialized = 1; + //mutex_unlock(p_cb_mutex); + rdp_init_netlink(); + //mutex_unlock(&(g_tty_driver_mutex)); + + DBGLOG(KERN_INFO "INFO\t[%s()]: done.", __func__); + return rv; +} + +void __exit rdp_exit(struct tty_driver * tty) { + struct rdp_tty * l_tty_driver = (struct rdp_tty *)NULL; + might_sleep(); + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + //mutex_lock(&(g_tty_driver_mutex)); + if (g_tty_driver != NULL && g_initialized > 0) { + l_tty_driver = g_tty_driver; + //smp_wmb(); + atomic_set(&(g_tty_driver->status), RDP_STATUS_EXIT); + } + g_initialized = 0; + //mutex_unlock(&(g_tty_driver_mutex)); + destroy_workqueue(g_cbq); + destroy_workqueue(g_writeq); + destroy_workqueue(g_readq); + destroy_workqueue(g_cmdq); + destroy_workqueue(g_complq); + //mutex_lock(&(g_tty_driver_mutex)); + if (g_tty_driver != NULL) { + if (g_tty_driver->driver != NULL) { + int i = 0; + for (i = 0; i < MAX_PORT; i++) { + if (g_ports[i].initialized) { + //mutex_lock(&(g_ports[i].mut)); + tty_unregister_device(g_tty_driver->driver, i); + g_ports[i].initialized = 0; + //mutex_unlock(&(g_ports[i].mut)); + } + } + } + g_tty_driver->driver = (struct tty_driver *)NULL; + g_tty_driver = (struct rdp_tty *)NULL; + //mutex_unlock(&(l_tty_driver->mut)); + memset(g_tty_driver, 0, sizeof(struct rdp_tty)); + kfree(l_tty_driver); + l_tty_driver = (struct rdp_tty *)NULL; + } + rdp_stop_netlink(); + p_cb_mutex = (struct mutex *)NULL; + DBGLOG(KERN_INFO "INFO\t[%s()]: done.", __func__); +} + +static void rdp_cmdw_handler(struct work_struct * work) { + unsigned long status = RDP_STATUS_ERROR; + //mutex_lock(&(g_tty_driver_mutex)); + if (g_tty_driver != NULL) { + //smp_rmb(); + status = atomic_read(&(g_tty_driver->status)); + if (g_tty_driver != NULL && status == RDP_STATUS_NORMAL) { + cmd_process_list(&rdp_outbound_cmd_list); + } + } + //mutex_unlock(&(g_tty_driver_mutex)); +} + +/* +static void rdp_complw_handler_old(struct work_struct * work) { + unsigned long flags; + completed_cmd_list_t * cmd_item = (completed_cmd_list_t *)NULL; + int lcompleted = 0; + struct list_head * ent = (struct list_head *)NULL; + struct list_head * n = (struct list_head *)NULL; + + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + + spin_lock_irqsave(&rdp_completed_cmds_lock, flags); + list_for_each_safe(ent, n, &rdp_completed_cmds) { + if (list_empty(&rdp_completed_cmds)) { + cmd_item = NULL; + } + else { + cmd_item = list_entry(ent, completed_cmd_list_t, list); + } + if (cmd_item != NULL && cmd_item->cmd != NULL) { + struct rdp_cmd * cmd = cmd_item->cmd; + //smp_rmb(); + lcompleted = atomic_read(&(cmd->completed)); + if (lcompleted == 1) { + smp_mb__before_atomic_inc(); + atomic_inc(&(cmd->completed)); + DBGLOG(KERN_INFO "INFO\t[%s()]: completing a cmd...", __func__); +// complete_all(cmd->done); + complete(cmd->done); + DBGLOG(KERN_INFO "INFO\t[%s()]: (completed)", __func__); + } + list_del_init(&(cmd_item->list)); + } + } + spin_unlock_irqrestore(&rdp_completed_cmds_lock, flags); + + DBGLOG(KERN_INFO "INFO\t[%s()]: done.", __func__); +} +*/ + +static void rdp_complw_handler(struct work_struct * work) { + unsigned long flags; + completed_cmd_list_t * cmd_item = (completed_cmd_list_t *)NULL; + int lcompleted = 0; + int i = 0; + + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + + spin_lock_irqsave(&rdp_completed_cmds_lock, flags); + for (i = 0; i < 16; i++) { + cmd_item = g_compl[i]; + if (cmd_item != NULL && cmd_item->cmd != NULL) { + struct rdp_cmd * cmd = (struct rdp_cmd *)NULL; + cmd = cmd_item->cmd; + //spin_lock(&(cmd->lock)); + //smp_rmb(); + lcompleted = atomic_read(&(cmd->completed)); + if (lcompleted >= 1) { + smp_mb__before_atomic_inc(); + atomic_inc(&(cmd->completed)); + if (cmd->done != NULL) { + DBGLOG(KERN_INFO "INFO\t[%s()]: completing a cmd...", __func__); + complete_all(cmd->done); + DBGLOG(KERN_INFO "INFO\t[%s()]: (completed)", __func__); + } + g_compl[i] = (completed_cmd_list_t *)NULL; + } + //spin_unlock(&(cmd->lock)); + } + } + spin_unlock_irqrestore(&rdp_completed_cmds_lock, flags); + + DBGLOG(KERN_INFO "INFO\t[%s()]: done.", __func__); +} + +static void rdp_readw_handler(struct work_struct * work) { + struct rdp_irq_entry * irq_entry = (struct rdp_irq_entry *)NULL; + struct rdp_irq_data * irq_data = (struct rdp_irq_data *)NULL; + struct tty_struct * tty = (struct tty_struct *)NULL; + unsigned char mut_locked = 0; + + might_sleep(); + + if (p_tty_mutex != NULL) { + //mutex_lock(p_tty_mutex); + mut_locked = 1; + } + //mutex_lock(&(g_tty_driver_mutex)); + if (g_tty_driver != NULL && mut_locked > 0) { + if (g_tty_driver->driver != NULL) { + read_deq(&irq_entry); + if (irq_entry != NULL) { + irq_data = irq_entry->data; + if (irq_entry->port != NULL && irq_data != NULL && irq_data->rx_len > 0 && irq_data->rx_buf != NULL && irq_entry->port->item != NULL && irq_entry->port->item->driver_data != NULL) { + struct rdptty_serial * rdp = (struct rdptty_serial *)NULL; + tty = irq_entry->port->item; + rdp = (struct rdptty_serial *)(tty->driver_data); + if (rdp != NULL) { + //mutex_lock(&(rdp->mut)); + rdp_receive(irq_entry->port, 0, &(irq_data->rx_len), irq_data->rx_buf); + //mutex_unlock(&(rdp->mut)); + } + } + } + } + } + mutex_unlock(&(g_tty_driver_mutex)); + if (p_tty_mutex != NULL && mut_locked > 0) { + mutex_unlock(p_tty_mutex); + } +} + +static void rdp_writew_handler(struct work_struct * work) { + unsigned long flags; + struct rdp_port * port = (struct rdp_port *)NULL; + struct rdp_write_entry * write_entry = (struct rdp_write_entry *)NULL; + unsigned char * buf = (unsigned char *)NULL; + int len = 0; + unsigned char mut_locked = 0; + int rv = 0; + + might_sleep(); + + if (p_tty_mutex != NULL) { + mutex_lock(p_tty_mutex); + mut_locked = 1; + } + mutex_lock(&(g_tty_driver_mutex)); + if (g_tty_driver != NULL && mut_locked > 0) { + if (g_tty_driver->driver != NULL) { + write_deq(&write_entry); + if (write_entry != NULL) { + spin_lock_irqsave(&(write_entry->lock), flags); + } + if (write_entry != NULL && write_entry->data != NULL && write_entry->len > 0 && write_entry->canceled != 1 && write_entry->completed < 1) { + port = write_entry->port; + len = write_entry->len; + buf = write_entry->data; + if (port != NULL && buf != NULL && len > 0) { + DBGLOG(KERN_INFO "INFO\t[%s()]: about to call cmd_exec(RDP_WRITE)...", __func__); + spin_unlock_irqrestore(&(write_entry->lock), flags); + cmd_exec(port, RDP_WRITE, buf, len, &rv, sizeof(int)); + spin_lock_irqsave(&(write_entry->lock), flags); + DBGLOG(KERN_INFO "INFO\t[%s()]: rv = %d", __func__, rv); + } + write_entry->rv = rv; + write_entry->completed = 1; + complete_all(&(write_entry->done)); + } + if (write_entry != NULL) { + spin_unlock_irqrestore(&(write_entry->lock), flags); + } + } + } + mutex_unlock(&(g_tty_driver_mutex)); + if (p_tty_mutex != NULL && mut_locked > 0) { + mutex_unlock(p_tty_mutex); + } +} diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/linux/drivers/serial/rdptty.c posixrdp/posixxrdp.orig/linux/drivers/serial/rdptty.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/linux/drivers/serial/rdptty.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/linux/drivers/serial/rdptty.c 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,827 @@ +/* + * RDP TTY driver + * + * Copyright (C) 2002-2010 Ryan Rafferty (ryanaxp@gmail.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ntddser.h" + +#define DRIVER_VERSION "v0.9" +#define DRIVER_AUTHOR "Ryan Rafferty " +#define DRIVER_DESC "RDP TTY driver" +#define DRIVER_LICENSE "GPL" + +/* Module information */ +MODULE_AUTHOR( DRIVER_AUTHOR ); +MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE( DRIVER_LICENSE ); + + +extern int __init rdp_ops_setup(struct tty_operations *); +extern int __init rdp_init(struct tty_driver *, struct mutex *); +extern void __exit rdp_exit(struct tty_driver *); + +#define C_RDP_TTY_MAJOR 240 /* experimental range */ +#define C_RDP_TTY_MINORS 4 /* only have 4 devices */ +#define C_RDP_TTY_NAME "rdptty" +#define C_RDP_TTY_DEV "ttyRDP" + +const unsigned int RDP_TTY_MAJOR = 240; +const unsigned int RDP_TTY_MINORS = 4; +const char RDP_TTY_NAME[] = "rdptty"; +const char RDP_TTY_DEV[] = "ttyRDP"; + +static int major = C_RDP_TTY_MAJOR; +static int minor = C_RDP_TTY_MINORS; +static char * name = (char *)NULL; +static char * dev = (char *)NULL; + +module_param(major, int, 0644); +MODULE_PARM_DESC(major, "TTY major device number (default: 240)"); +module_param(minor, int, 0644); +MODULE_PARM_DESC(minor, "TTY minor device number (default: 4)"); +module_param(name, charp, 0644); +MODULE_PARM_DESC(name, "TTY device identifier (default: \"rdptty\")"); +module_param(dev, charp, 0644); +MODULE_PARM_DESC(dev, "TTY device node filename (default: \"ttyRDP\")"); + +extern struct rdp_port g_ports[MAX_PORT]; + +static struct tty_operations rdp_tty_ops; + +static DEFINE_MUTEX(g_tty_mutex); +static struct mutex * p_tty_mutex = (struct mutex *)NULL; + +struct rdp_port * rdptty_table[C_RDP_TTY_MINORS]; /* initially all NULL */ + +static int rdptty_open(struct tty_struct * tty, struct file * file) { + struct rdp_port * rdp = (struct rdp_port *)NULL; + int index = 0; + int rv = 0; + + might_sleep(); + + printk(KERN_DEBUG "INFO\t[%s()]: called", __FUNCTION__); + + if (p_tty_mutex != NULL) { + mutex_lock(p_tty_mutex); + } + if (tty == NULL) { + rv = -ENODEV; + goto exit; + } + + /* initialize the pointer in case something fails */ + tty->driver_data = NULL; + + /* get the serial object associated with this tty pointer */ + index = tty->index; + rdp = rdptty_table[index]; + if (rdp == NULL) { + /* first time accessing this device, let's create it */ + rdp = &(g_ports[index]); + if (rdp == NULL) { + rv = -ENOMEM; + goto exit; + } + else { + mutex_init(&(rdp->mut)); + mutex_lock(&(rdp->mut)); + atomic_set(&(rdp->open_count), 0); + rdptty_table[index] = rdp; + } + } + else { + mutex_lock(&(rdp->mut)); + } + + if (rdp_tty_ops.open) { + rv = (rdp_tty_ops.open(tty, file) > 0) ? 0 : -EIO; + } + + /* save our structure within the tty structure */ + tty->driver_data = rdp; + rdp->tty = tty; + smp_mb__before_atomic_inc(); + atomic_inc(&(rdp->open_count)); + if (atomic_read(&(rdp->open_count)) == 1) { + /* this is the first time this port is opened */ + /* do any hardware initialization needed here */ + } + + mutex_unlock(&(rdp->mut)); + + exit:; + if (p_tty_mutex != NULL) { + mutex_unlock(p_tty_mutex); + } + printk(KERN_DEBUG "INFO\t[%s()]: done.", __FUNCTION__); + return rv; +} + +static void do_close(struct rdp_port * rdp) { + if (rdp != NULL) { + if (atomic_read(&(rdp->open_count)) > 0) { + smp_mb__before_atomic_dec(); + atomic_dec(&(rdp->open_count)); + if (atomic_read(&(rdp->open_count)) <= 0) { + /* The port is being closed by the last user. */ + /* Do any hardware specific stuff here */ + } + } + } +} + +static void rdptty_close(struct tty_struct * tty, struct file * file) { + struct rdp_port * rdp = (struct rdp_port *)NULL; + + might_sleep(); + + printk(KERN_DEBUG "INFO\t[%s()]: called", __FUNCTION__); + + if (p_tty_mutex != NULL) { + mutex_lock(p_tty_mutex); + } + if (tty != NULL) { + rdp = tty->driver_data; + } + if (rdp) { + mutex_lock(&(rdp->mut)); + do_close(rdp); + if (rdp_tty_ops.close) { + rdp_tty_ops.close(tty, file); + } + mutex_unlock(&(rdp->mut)); + } + if (p_tty_mutex != NULL) { + mutex_unlock(p_tty_mutex); + } + printk(KERN_DEBUG "INFO\t[%s()]: done.", __FUNCTION__); +} + +static int rdptty_putchar(struct tty_struct * tty, const unsigned char ch) { + struct rdp_port * rdp = (struct rdp_port *)NULL; + int retval = -EINVAL; + char cbuf[2] = {0x00, 0x00}; + + printk(KERN_DEBUG "INFO\t[%s()]: called", __FUNCTION__); + + if (tty != NULL && tty->driver_data != NULL) { + rdp = (struct rdp_port *)(tty->driver_data); + } + + if (rdp == NULL) { + retval = -ENODEV; + } + else { + + if (atomic_read(&(rdp->open_count)) < 1) { + /* port was not opened */ + goto exit; + } + + if (rdp_tty_ops.write) { + cbuf[0] = ch; + retval = rdp_tty_ops.write(tty, cbuf, 1); + printk("INFO\t[%s()]: retval = %d", __FUNCTION__, retval); + } + + /* fake sending the data out a hardware port by + * writing it to the kernel debug log. + */ + printk(KERN_DEBUG "%s - ", __FUNCTION__); + printk("%02x\t(\"%c\")\n", ch, ch); + + exit:; + + } + + printk(KERN_DEBUG "INFO\t[%s()]: done.", __FUNCTION__); + return retval; +} + +static int rdptty_write(struct tty_struct * tty, const unsigned char * buffer, int count) { + struct rdp_port * rdp = (struct rdp_port *)NULL; + int i = 0; + int retval = -EINVAL; + + printk(KERN_DEBUG "INFO\t[%s()]: called", __FUNCTION__); + + if (tty != NULL && tty->driver_data != NULL) { + rdp = (struct rdp_port *)(tty->driver_data); + } + + if (rdp == NULL) { + retval = -ENODEV; + } + else { + + if (atomic_read(&(rdp->open_count)) < 1) { + /* port was not opened */ + goto exit; + } + + if (rdp_tty_ops.write) { + retval = rdp_tty_ops.write(tty, buffer, count); + printk("INFO\t[%s()]: retval = %d", __FUNCTION__, retval); + } + + /* fake sending the data out a hardware port by + * writing it to the kernel debug log. + */ + printk(KERN_DEBUG "%s - ", __FUNCTION__); + for (i = 0; i < count; ++i) { + printk("%02x ", buffer[i]); + } + printk("\t(\""); + for (i = 0; i < count; ++i) { + printk("%c", buffer[i]); + } + printk("\")\n"); + + exit:; + } + + printk(KERN_DEBUG "INFO\t[%s()]: done.", __FUNCTION__); + return retval; +} + +static int rdptty_write_room(struct tty_struct * tty) { + struct rdp_port * rdp = (struct rdp_port *)NULL; + int room = -EINVAL; + + might_sleep(); + + printk(KERN_DEBUG "INFO\t[%s()]: called", __FUNCTION__); + + if (p_tty_mutex != NULL) { + mutex_lock(p_tty_mutex); + } + + if (likely(tty != NULL)) { + rdp = (struct rdp_port *)(tty->driver_data); + } + if (unlikely(rdp == NULL)) { + room = -ENODEV; + } + else { + mutex_lock(&(rdp->mut)); + if (atomic_read(&(rdp->open_count)) > 0) { + /* calculate how much room is left in the device */ + //room = 255; + room = 1; + } + mutex_unlock(&(rdp->mut)); + } + if (p_tty_mutex != NULL) { + mutex_unlock(p_tty_mutex); + } + printk(KERN_DEBUG "INFO\t[%s()]: done.", __FUNCTION__); + return room; +} + +#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) + +static void rdptty_set_termios(struct tty_struct * tty, struct ktermios * old_termios) { + unsigned int cflag = 0; + + might_sleep(); + + printk(KERN_DEBUG "INFO\t[%s()]: called", __FUNCTION__); + + if (p_tty_mutex != NULL) { + mutex_lock(p_tty_mutex); + } + if (tty != NULL && tty->termios != NULL) { + cflag = tty->termios->c_cflag; + } + + /* check that they really want us to change something */ + if (old_termios) { + if ((cflag == old_termios->c_cflag) && (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { + printk(KERN_DEBUG " - nothing to change...\n"); + if (p_tty_mutex != NULL) { + mutex_unlock(p_tty_mutex); + } + return; + } + } + + /* get the byte size */ + switch (cflag & CSIZE) { + case CS5: + printk(KERN_DEBUG " - data bits = 5\n"); + break; + case CS6: + printk(KERN_DEBUG " - data bits = 6\n"); + break; + case CS7: + printk(KERN_DEBUG " - data bits = 7\n"); + break; + case CS8: + default: + printk(KERN_DEBUG " - data bits = 8\n"); + break; + } + + /* determine the parity */ + if (cflag & PARENB) { + if (cflag & PARODD) { + printk(KERN_DEBUG " - parity = odd\n"); + } + else { + printk(KERN_DEBUG " - parity = even\n"); + } + } + else { + printk(KERN_DEBUG " - parity = none\n"); + } + + /* figure out the stop bits requested */ + if (cflag & CSTOPB) { + printk(KERN_DEBUG " - stop bits = 2\n"); + } + else { + printk(KERN_DEBUG " - stop bits = 1\n"); + } + + /* figure out the hardware flow control settings */ + if (cflag & CRTSCTS) { + printk(KERN_DEBUG " - RTS/CTS is enabled\n"); + } + else { + printk(KERN_DEBUG " - RTS/CTS is disabled\n"); + } + + /* determine software flow control */ + /* if we are implementing XON/XOFF, set the start and */ + /* stop character in the device */ + if (I_IXOFF(tty) || I_IXON(tty)) { + unsigned char stop_char = STOP_CHAR(tty); + unsigned char start_char = START_CHAR(tty); + + /* if we are implementing INBOUND XON/XOFF */ + if (I_IXOFF(tty)) { + printk(KERN_DEBUG " - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", start_char, stop_char); + } + else { + printk(KERN_DEBUG" - INBOUND XON/XOFF is disabled"); + } + /* if we are implementing OUTBOUND XON/XOFF */ + if (I_IXON(tty)) { + printk(KERN_DEBUG" - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", start_char, stop_char); + } + else { + printk(KERN_DEBUG" - OUTBOUND XON/XOFF is disabled"); + } + } + + /* get the baud rate wanted */ + printk(KERN_DEBUG " - baud rate = %d", tty_get_baud_rate(tty)); + printk(KERN_DEBUG "INFO\t[%s()]: done.", __FUNCTION__); + if (p_tty_mutex != NULL) { + mutex_unlock(p_tty_mutex); + } +} + +/* Our fake UART values */ +#define MCR_DTR 0x01 +#define MCR_RTS 0x02 +#define MCR_LOOP 0x04 +#define MSR_CTS 0x08 +#define MSR_CD 0x10 +#define MSR_RI 0x20 +#define MSR_DSR 0x40 + +static int rdptty_tiocmget(struct tty_struct * tty, struct file * file) { + struct rdp_port * rdp = (struct rdp_port *)NULL; + unsigned int result = 0; + unsigned int msr = 0; + unsigned int mcr = 0; + + if (p_tty_mutex != NULL) { + mutex_lock(p_tty_mutex); + } + if (tty != NULL && tty->driver_data != NULL) { + rdp = (struct rdp_port *)(tty->driver_data); + + mutex_lock(&(rdp->mut)); + + msr = rdp->msr; + mcr = rdp->mcr; + + mutex_unlock(&(rdp->mut)); + + result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) | /* DTR is set */ + ((mcr & MCR_RTS) ? TIOCM_RTS : 0) | /* RTS is set */ + ((mcr & MCR_LOOP) ? TIOCM_LOOP : 0) | /* LOOP is set */ + ((msr & MSR_CTS) ? TIOCM_CTS : 0) | /* CTS is set */ + ((msr & MSR_CD) ? TIOCM_CAR : 0) | /* Carrier detect is set*/ + ((msr & MSR_RI) ? TIOCM_RI : 0) | /* Ring Indicator is set */ + ((msr & MSR_DSR) ? TIOCM_DSR : 0); /* DSR is set */ + } + if (p_tty_mutex != NULL) { + mutex_unlock(p_tty_mutex); + } + + return result; +} + +static int rdptty_tiocmset(struct tty_struct * tty, struct file * file, unsigned int set, unsigned int clear) { + struct rdp_port * rdp = (struct rdp_port *)NULL; + unsigned int mcr = 0; + + if (p_tty_mutex != NULL) { + mutex_lock(p_tty_mutex); + } + if (tty != NULL && tty->driver_data != NULL) { + rdp = (struct rdp_port *)tty->driver_data; + mcr = rdp->mcr; + + if (set & TIOCM_RTS) { + mcr |= MCR_RTS; + } + if (set & TIOCM_DTR) { + mcr |= MCR_RTS; + } + + if (clear & TIOCM_RTS) { + mcr &= ~MCR_RTS; + } + if (clear & TIOCM_DTR) { + mcr &= ~MCR_RTS; + } + + /* set the new MCR value in the device */ + rdp->mcr = mcr; + } + if (p_tty_mutex != NULL) { + mutex_unlock(p_tty_mutex); + } + return 0; +} + +/* +static int rdptty_read_proc(char *page, char **start, off_t off, int count, + int *eof, void *data) { + struct rdp_port * rdp = (struct rdp_port *)NULL; + off_t begin = 0; + int length = 0; + int i = 0; + + length += sprintf(page, "rdpserinfo:1.0 driver:%s\n", DRIVER_VERSION); + for (i = 0; i < RDP_TTY_MINORS && length < PAGE_SIZE; ++i) { + rdp = rdptty_table[i]; + if (rdp == NULL) { + continue; + } + length += sprintf(page+length, "%d\n", i); + if ((length + begin) > (off + count)) { + goto done; + } + if ((length + begin) < off) { + begin += length; + length = 0; + } + } + *eof = 1; + done: + if (off >= (length + begin)) { + return 0; + } + *start = page + (off-begin); + return (count < begin+length-off) ? count : begin + length-off; +} +*/ + +#define rdptty_ioctl rdptty_ioctl_tiocgserial +static int rdptty_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg) { + struct rdp_port * rdp = (struct rdp_port *)NULL; + int rv = -ENOIOCTLCMD; + + printk(KERN_INFO "INFO\t[%s()]: called", __FUNCTION__); + + if (p_tty_mutex != NULL) { + mutex_lock(p_tty_mutex); + } + if (tty != NULL && tty->driver_data != NULL) { + rdp = (struct rdp_port *)(tty->driver_data); + mutex_lock(&(rdp->mut)); + if (cmd == TIOCGSERIAL) { + struct serial_struct tmp; + if (!arg) { + rv = -EFAULT; + } + else { + memset(&tmp, 0, sizeof(struct serial_struct)); + tmp.type = rdp->serial.type; + tmp.line = rdp->serial.line; + tmp.port = rdp->serial.port; + tmp.irq = rdp->serial.irq; + tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; + tmp.xmit_fifo_size = rdp->serial.xmit_fifo_size; + tmp.baud_base = rdp->serial.baud_base; + tmp.close_delay = 5*HZ; + tmp.closing_wait = 30*HZ; + tmp.custom_divisor = rdp->serial.custom_divisor; + tmp.hub6 = rdp->serial.hub6; + tmp.io_type = rdp->serial.io_type; + if (copy_to_user((void __user *)arg, &tmp, sizeof(struct serial_struct))) { + rv = -EFAULT; + } + else { + rv = 0; + } + } + } + mutex_unlock(&(rdp->mut)); + } + if (p_tty_mutex != NULL) { + mutex_unlock(p_tty_mutex); + } + return rv; +} +#undef rdptty_ioctl + +#define rdptty_ioctl rdptty_ioctl_tiocmiwait +static int rdptty_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg) { + struct rdp_port * rdp = (struct rdp_port *)NULL; + int do_up = 1; + + printk(KERN_INFO "INFO\t[%s()]: called", __FUNCTION__); + + if (p_tty_mutex != NULL) { + mutex_lock(p_tty_mutex); + } + if (tty != NULL && tty->driver_data != NULL) { + rdp = (struct rdp_port *)(tty->driver_data); + mutex_lock(&(rdp->mut)); + if (cmd == TIOCMIWAIT) { + DECLARE_WAITQUEUE(wait, current); + struct async_icount cnow; + struct async_icount cprev; + + cprev = rdp->icount; + mutex_unlock(&(rdp->mut)); + mutex_unlock(p_tty_mutex); + do_up = 0; + while (1) { + add_wait_queue(&rdp->wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + remove_wait_queue(&rdp->wait, &wait); + + /* see if a signal woke us up */ + if (signal_pending(current)) { + return -ERESTARTSYS; + } + + cnow = rdp->icount; + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { + return -EIO; /* no change => error */ + } + if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { + return 0; + } + cprev = cnow; + } + + } + else { + mutex_unlock(&(rdp->mut)); + mutex_unlock(p_tty_mutex); + do_up = 0; + } + } + if (do_up > 0 && p_tty_mutex != NULL) { + mutex_unlock(p_tty_mutex); + } + return -ENOIOCTLCMD; +} +#undef rdptty_ioctl + +#define rdptty_ioctl rdptty_ioctl_tiocgicount +static int rdptty_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) { + struct rdp_port * rdp = (struct rdp_port *)NULL; + + printk(KERN_INFO "INFO\t[%s()]: called", __FUNCTION__); + + if (p_tty_mutex != NULL) { + mutex_lock(p_tty_mutex); + } + if (tty != NULL && tty->driver_data != NULL) { + rdp = (struct rdp_port *)(tty->driver_data); + mutex_lock(&(rdp->mut)); + if (cmd == TIOCGICOUNT) { + struct async_icount cnow = rdp->icount; + struct serial_icounter_struct icount; + + icount.cts = cnow.cts; + icount.dsr = cnow.dsr; + icount.rng = cnow.rng; + icount.dcd = cnow.dcd; + icount.rx = cnow.rx; + icount.tx = cnow.tx; + icount.frame = cnow.frame; + icount.overrun = cnow.overrun; + icount.parity = cnow.parity; + icount.brk = cnow.brk; + icount.buf_overrun = cnow.buf_overrun; + + if (copy_to_user((void __user *)arg, &icount, sizeof(icount))) { + mutex_unlock(&(rdp->mut)); + mutex_unlock(p_tty_mutex); + return -EFAULT; + } + else { + mutex_unlock(&(rdp->mut)); + mutex_unlock(p_tty_mutex); + return 0; + } + } + mutex_unlock(&(rdp->mut)); + } + if (p_tty_mutex != NULL) { + mutex_unlock(p_tty_mutex); + } + return -ENOIOCTLCMD; +} +#undef rdptty_ioctl + +/* the real rdptty_ioctl function. The above is done to get the small functions in the book */ +static int rdptty_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg) { + + printk(KERN_DEBUG "INFO\t[%s()]: called", __FUNCTION__); + + switch (cmd) { + case TIOCGSERIAL: + return rdptty_ioctl_tiocgserial(tty, file, cmd, arg); + break; + case TIOCMIWAIT: + return rdptty_ioctl_tiocmiwait(tty, file, cmd, arg); + break; + case TIOCGICOUNT: + return rdptty_ioctl_tiocgicount(tty, file, cmd, arg); + break; + } + + printk(KERN_DEBUG "INFO\t[%s()]: done.", __FUNCTION__); + return -ENOIOCTLCMD; +} + +static struct tty_operations serial_ops = { + .open = rdptty_open, + .close = rdptty_close, + .put_char = rdptty_putchar, + .write = rdptty_write, + .write_room = rdptty_write_room, + .set_termios = rdptty_set_termios, + .tiocmget = rdptty_tiocmget, + .tiocmset = rdptty_tiocmset, + .ioctl = rdptty_ioctl, +}; + +static struct tty_driver * rdptty_tty_driver = (struct tty_driver *)NULL; + +int __init rdptty_init(void) { + int retval = 0; + int l_major = RDP_TTY_MAJOR; + int l_minor = RDP_TTY_MINORS; + char * l_name = (char *)RDP_TTY_NAME; + char * l_dev = (char *)RDP_TTY_DEV; + + printk(KERN_DEBUG "INFO\t[%s()]: called", __FUNCTION__); + + memset(&g_tty_mutex, 0x00, sizeof(struct mutex)); + p_tty_mutex = &g_tty_mutex; + mutex_init(p_tty_mutex); + mutex_lock(p_tty_mutex); + + if (major > 0) { + l_major = major; + } + if (minor > 0) { + l_minor = minor; + } + if (name != NULL && strlen(name) > 0 && strlen(name) < 33) { + l_name = name; + } + if (dev != NULL && strlen(dev) > 0 && strlen(dev) < 33) { + l_dev = dev; + } + + + /* allocate the tty driver */ + rdptty_tty_driver = alloc_tty_driver(l_minor); + if (!rdptty_tty_driver) { + retval = -ENOMEM; + goto end; + } + + memset(&rdp_tty_ops, 0, sizeof(struct tty_operations)); + rdp_ops_setup(&rdp_tty_ops); + + /* initialize the tty driver */ + rdptty_tty_driver->owner = THIS_MODULE; + rdptty_tty_driver->driver_name = l_name; + rdptty_tty_driver->name = l_dev; + /* no more devfs subsystem */ + rdptty_tty_driver->major = l_major; + rdptty_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; + rdptty_tty_driver->subtype = SERIAL_TYPE_NORMAL; +// rdptty_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_RESET_TERMIOS; + rdptty_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + /* no more devfs subsystem */ + rdptty_tty_driver->init_termios = tty_std_termios; + rdptty_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + + tty_set_operations(rdptty_tty_driver, &serial_ops); + + /* register the tty driver */ + retval = tty_register_driver(rdptty_tty_driver); + if (retval) { + printk(KERN_ERR "failed to register rdp tty driver"); + put_tty_driver(rdptty_tty_driver); + } + else { + rdp_init(rdptty_tty_driver, p_tty_mutex); + printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION); + } + + end:; + if (p_tty_mutex != NULL) { + mutex_unlock(p_tty_mutex); + } + return retval; +} + +void __exit rdptty_exit(void) { + int i = 0; + + printk(KERN_DEBUG "INFO\t[%s()]: called", __FUNCTION__); + + if (p_tty_mutex != NULL) { + mutex_lock(p_tty_mutex); + } + + /* shut down all of the timers and free the memory */ + if (1==2) { +// { +// struct rdptty_serial * rdp = (struct rdptty_serial *)NULL; + struct rdp_port * rdp = (struct rdp_port *)NULL; + for (i = 0; i < RDP_TTY_MINORS; ++i) { + rdp = rdptty_table[i]; + if (rdp != NULL) { +// mutex_lock(&(rdp->mut)); + /* close the port */ + while (atomic_read(&(rdp->open_count)) > 0) { +// do_close(rdp); +// if (rdp_tty_ops.close) { +// rdp_tty_ops.close(rdp->tty, NULL); +// } + } +// rdptty_table[i] = NULL; +// mutex_unlock(&(rdp->mut)); + } + } + } + + rdp_exit(rdptty_tty_driver); + tty_unregister_driver(rdptty_tty_driver); + put_tty_driver(rdptty_tty_driver); + if (p_tty_mutex != NULL) { + mutex_unlock(p_tty_mutex); + } + p_tty_mutex = (struct mutex *)NULL; + + printk(KERN_DEBUG "INFO\t[%s()]: done.", __FUNCTION__); +} + +module_init(rdptty_init); +module_exit(rdptty_exit); diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/linux/drivers/serial/rdpuart.c posixrdp/posixxrdp.orig/linux/drivers/serial/rdpuart.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/linux/drivers/serial/rdpuart.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/linux/drivers/serial/rdpuart.c 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,1858 @@ +/* + * rdpuart.c: Virtual serial port driver for RDP + * + * Copyright (C) 2010, Ryan Rafferty. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include "ntddser.h" + + +/*** + *** Default constants for this module + ***/ + +#define RDPUART_TITLE "rdpuart" +#define RDPUART_NAME "ttyRDP" +#define RDPUART_MAJOR 240 +#define RDPUART_MINOR 186 +#define RDPUART_NR_UARTS 2 +#define RDPUART_MAX_UARTS 32 +#define RDPUART_ALIAS "platform:rdpuart" +#define RDPUART_NR_IRQ 0 + +/* --------------------------------------------------------------------- + * + * Register definitions + * + */ +#ifndef LINUX_RDPUART_REGS +#define LINUX_RDPUART_REGS + +#define RDPUART_RX 0x00 +#define RDPUART_TX 0x04 +#define RDPUART_STATUS 0x08 +#define RDPUART_CONTROL 0x0c + +#define RDPUART_REGION 16 + +#define RDPUART_STATUS_RXVALID 0x01 +#define RDPUART_STATUS_RXFULL 0x02 +#define RDPUART_STATUS_TXEMPTY 0x04 +#define RDPUART_STATUS_TXFULL 0x08 +#define RDPUART_STATUS_IE 0x10 +#define RDPUART_STATUS_OVERRUN 0x20 +#define RDPUART_STATUS_FRAME 0x40 +#define RDPUART_STATUS_PARITY 0x80 + +#define RDPUART_CONTROL_RST_TX 0x01 +#define RDPUART_CONTROL_RST_RX 0x02 +#define RDPUART_CONTROL_IE 0x10 + +#endif /* LINUX_RDPUART_REGS */ + + +/*** + *** convenience macros + ***/ + +#define is_real_interrupt(x) ((x == 0) ? x : 0) + +#ifndef MINVAL +#define MINVAL(x,y) (((x) > (y)) ? (y) : (x)) +#endif + +#define ASCIICHR(x) (((x) > 31 && x < 127) ? x : 0x20) +#define DBGLOG(...) { \ + printk(__VA_ARGS__); \ + printk("\n"); \ +} +#define RDPUARTCMD(x) (cmdarray[(x & 0x1f)]) +static const char * cmdarray[] = CMD_TO_STRING_ARRAY_DEF; + + +/*** + *** static function prototypes + ***/ + +static int rdpuart_receive(struct rdpuart_port *, int, int, char *); +static int __devinit rdpuart_probe(struct platform_device *); +static int __devexit rdpuart_remove(struct platform_device *); + + +/*** + *** static structs + ***/ + +static struct platform_driver rdpuart_platform_driver = { + .probe = rdpuart_probe, + .remove = __devexit_p(rdpuart_remove), + .driver = { + .owner = THIS_MODULE, + .name = RDPUART_TITLE, + }, +}; + + +/*** + *** static global variables + ***/ + +static int g_already_opened = 0; +static int g_stop = 1; +static struct uart_port * g_port = (struct uart_port *)NULL; +static struct platform_device * gdev = (struct platform_device *)NULL; +static struct rdpuart_port rdpuart_ports[RDPUART_MAX_UARTS]; + +#define Q_NAME "rdpuart_work_queue" +static int g_exit = 0; +static void rdpuart_cmdw_handler(struct work_struct *); +static struct workqueue_struct * g_cmdq; +static DECLARE_DELAYED_WORK(g_cmdw, rdpuart_cmdw_handler); + +static int major = RDPUART_MAJOR; +static int minor = RDPUART_MINOR; +static int nr = RDPUART_NR_UARTS; +static char * title = RDPUART_TITLE; +static char * name = RDPUART_NAME; + +module_param(major, int, 0744); +module_param(minor, int, 0744); +module_param(nr, int, 0744); +module_param(title, charp, 0744); +module_param(name, charp, 0744); + + +/*** + *** Netlink Connection ("cn") functions + ***/ + +static struct rdpuart_family rdpuart_default_family = {}; + +typedef struct rdpuart_cmd { + unsigned char cmd; + void * idata; + int ilen; + void * odata; + int olen; + + int seqid; + unsigned char completed; + struct list_head list; + + struct rdpuart_record * rec; + struct rdpuart_port * port; + + int cmd_idx; +} rdpuart_cmd_t; + +static DEFINE_SPINLOCK(rdpuart_cmd_outbound_flock); +static LIST_HEAD(rdpuart_outbound_cmd_list); + +DEFINE_SPINLOCK(rdpuart_flock); +static LIST_HEAD(rdpuart_families); + +static DEFINE_SPINLOCK(rdpuart_cmd_list_flock); +static LIST_HEAD(rdpuart_pending_cmd_list); +static DECLARE_WAIT_QUEUE_HEAD(pending_cmd_reply_waitq); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30) +# define CBARGS struct cn_msg * imsg, struct netlink_skb_parms * parms +#else +# define CBARGS void * imsg +#endif +static void rdpuart_cn_callback(CBARGS) { + int found = 0; + int mlen = 0; + uint8_t mtype = 0x00; + struct cn_msg * msg = (struct cn_msg *)imsg; + rdpuart_netlink_msg * m = (rdpuart_netlink_msg *)(msg + 1); + if (msg == NULL) { + DBGLOG(KERN_ERR "ERROR\t[rdpuart_cn_callback()]: msg is a null pointer"); + } + else { + DBGLOG(KERN_INFO "INFO\t[rdpuart_cn_callback()]: called"); + while (msg->len) { + struct rdpuart_cmd * cmd = (struct rdpuart_cmd *)NULL; + struct list_head * ent = (struct list_head *)NULL; + struct list_head * n = (struct list_head *)NULL; + rdpuart_reg_num id; + memcpy(&id, m->id.id, sizeof(rdpuart_reg_num)); + //DBGLOG(KERN_INFO "INFO\t[%s()]: {cn_msg} idx = \"%d\", val = \"%d\", seqid = \"%d\", ack = \"%d\", len = \"%d\";", __func__, msg->id.idx, msg->id.val, msg->seq, msg->ack, msg->len); + //DBGLOG(KERN_INFO "INFO\t[%s()]: {rdpuart_netlink_msg} %02x-%012llx.%02x --> type = \"%02x\", len= \"%u\".", __func__, id.family, (unsigned long long)id.id, id.crc, m->type, m->len); + mtype |= m->type; + mlen = m->len; + if (msg->ack > 0) { + //DBGLOG(KERN_INFO "INFO\t[%s()]: msg->ack = \"%d\"", __func__, msg->ack); + spin_lock(&rdpuart_cmd_list_flock); + list_for_each_safe(ent, n, &rdpuart_pending_cmd_list) { + cmd = list_entry(ent, struct rdpuart_cmd, list); + //DBGLOG(KERN_INFO "INFO\t[%s()]: (seqid = \"%d\")", __func__, cmd->seqid); + if (cmd->seqid == msg->seq) { + //DBGLOG(KERN_INFO "INFO\t[%s()]: seqid \"%d\" (cmd_idx = \"%d\") about to be marked \"completed\"", __func__, cmd->seqid, cmd->cmd_idx); + found = 1; + cmd->completed = 1; + spin_lock(&(cmd->port->cmd_lock)); + cmd->port->cmd_array[(cmd->cmd_idx)] = 0; + spin_unlock(&(cmd->port->cmd_lock)); + break; + } + } + spin_unlock(&rdpuart_cmd_list_flock); + if (found > 0) { + wake_up_interruptible_all(&pending_cmd_reply_waitq); + } + } + else if (mtype > 0) { + /* if an unsolicited cn packet is received, then it should be handled as a + * "virtual interrupt" received from the userspace daemon; so, queue up an + * ersatz irq handler: + */ + struct rdpuart_irq_data * irq_data = (struct rdpuart_irq_data *)(m->data); + mtype &= ~RDPUART_ASYNC; + switch (mtype) { + case RDPUART_ADDPORT: + { + struct resource * tarr = (struct resource *)NULL; + struct resource * iomem = (struct resource *)NULL; + struct resource * irq = (struct resource *)NULL; + struct resource rarr[2]; + memset(rarr,0,sizeof(struct resource)*2); + if (rarr == NULL) { + } + else { + resource_size_t start = 0; + resource_size_t end = 0; + void * membuf = (void *)NULL; + #if PAGE_SIZE > 3999 + membuf = (void *)get_zeroed_page(GFP_KERNEL); + start = (resource_size_t)membuf; + end = (resource_size_t)(membuf + PAGE_SIZE); + #else + membuf = kzalloc(4000, GFP_KERNEL); + start = (resource_size_t)membuf; + end = (resource_size_t)(membuf + 4000); + #endif + { + struct resource liomem = { + .start = start, + .end = end, + .flags = IORESOURCE_MEM, + }; + struct resource lirq = { + .start = (resource_size_t)RDPUART_NR_IRQ, + .end = (resource_size_t)RDPUART_NR_IRQ, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE, + }; + iomem = &(rarr[0]); + irq = &(rarr[1]); + memcpy(iomem,&liomem,sizeof(struct resource)); + memcpy(irq,&lirq,sizeof(struct resource)); + } + } + tarr = (struct resource *)kzalloc(sizeof(rarr), GFP_KERNEL); + memcpy(tarr,rarr,sizeof(rarr)); + DBGLOG(KERN_INFO "INFO\t[%s()]: calling platform_device_register_simple() {rdpuart_platform_driver.driver.bus = \"%p\"}", __func__, rdpuart_platform_driver.driver.bus); + if (!(gdev = platform_device_register_simple(title, -1, tarr, ARRAY_SIZE(rarr)))) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: platform_device_register_simple() failed", __func__); + } + } + break; + case RDPUART_RXFULL: + { + int idx = 0; + int found = 0; + for (idx = 0; idx < nr; idx++) { + if (rdpuart_ports[idx].device_id == irq_data->device_id) { + found = 1; + break; + } + } + if (found > 0) { + rdpuart_receive(&(rdpuart_ports[idx]), RDPUART_STATUS_RXVALID, irq_data->rx_len, irq_data->rx_buf); + } + else { + rdpuart_receive(&(rdpuart_ports[0]), RDPUART_STATUS_RXVALID, irq_data->rx_len, irq_data->rx_buf); + } + } + break; + default: + { + DBGLOG(KERN_WARNING "WARNING\t[%s()]: INTERRUPT --> unrecognized opcode (\"0x%02x\")", __func__, mtype); + } + break; + } + } + msg->len -= sizeof(rdpuart_netlink_msg) + m->len; + m = (rdpuart_netlink_msg *)(((u8 *)m) + m->len); + } + } +} + +int rdpuart_netlink_send(struct rdpuart_record * dev, rdpuart_netlink_msg * msg, int memmode) { + int rv = 0; + //char buf[sizeof(struct cn_msg) + sizeof(rdpuart_netlink_msg)]; + char buf[512]; + struct cn_msg * m = (struct cn_msg *)buf; + rdpuart_netlink_msg * w = (rdpuart_netlink_msg *)(m+1); + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + if (dev == NULL) { + DBGLOG(KERN_WARNING "WARNING\t[%s()]: dev is a null pointer", __func__); + rv = -EINVAL; + goto end; + } + if (msg == NULL) { + DBGLOG(KERN_WARNING "WARNING\t[%s()]: msg is a null pointer", __func__); + rv = -EINVAL; + goto end; + } + memset(buf, 0, sizeof(buf)); + m->id.idx = CN_IDX_RDPUART; + m->id.val = CN_VAL_RDPUART; + spin_lock(&(dev->lock)); + m->seq = dev->seq++; + spin_unlock(&(dev->lock)); + rv = m->seq; + //if (m->len < sizeof(rdpuart_netlink_msg) || m->len > (sizeof(struct cn_msg) + sizeof(rdpuart_netlink_msg))) { + // m->len = sizeof(rdpuart_netlink_msg); + //} + m->len = sizeof(rdpuart_netlink_msg) + msg->len; + DBGLOG(KERN_INFO "INFO\t[%s()]: about to call memcpy()...", __func__); + memcpy(w, msg, m->len); + DBGLOG(KERN_INFO "INFO\t[%s()]: about to call cn_netlink_send()... {m->len = \"%d\"}", __func__, m->len); + cn_netlink_send(m, 0, memmode); + end: + DBGLOG(KERN_INFO "INFO\t[%s()]: done (rv = \"%d\").", __func__, rv); + return rv; +} + + +int rdpuart_init_netlink(void) { + int rv = 0; + struct cb_id rdpuart_id = { + .idx = CN_IDX_RDPUART, + .val = CN_VAL_RDPUART, + }; + DBGLOG(KERN_INFO "INFO\t[rdpuart_init_netlink()]: called"); + rv = cn_add_callback(&rdpuart_id, "rdpuart", &rdpuart_cn_callback); + return rv; +} + +void rdpuart_stop_netlink(void) { + struct cb_id rdpuart_id = { + .idx = CN_IDX_RDPUART, + .val = CN_VAL_RDPUART, + }; + DBGLOG(KERN_INFO "INFO\t[rdpuart_stop_netlink()]: called"); + cn_del_callback(&rdpuart_id); +} + +int rdpuart_register_family(struct rdpuart_family * newf) { + struct list_head * ent = (struct list_head *)NULL; + struct list_head * n = (struct list_head *)NULL; + struct rdpuart_family * f = (struct rdpuart_family *)NULL; + int ret = 0; + + spin_lock(&rdpuart_flock); + list_for_each_safe(ent, n, &rdpuart_families) { + f = list_entry(ent, struct rdpuart_family, family_entry); + if (f->fid == newf->fid) { + ret = -EEXIST; + break; + } + } + + if (!ret) { + atomic_set(&newf->refcnt, 0); + newf->need_exit = 0; + list_add_tail(&newf->family_entry, &rdpuart_families); + } + spin_unlock(&rdpuart_flock); + + return ret; +} + +void rdpuart_unregister_family(struct rdpuart_family * fent) { + struct list_head * ent = (struct list_head *)NULL; + struct list_head * n = (struct list_head *)NULL; + struct rdpuart_family * f = (struct rdpuart_family *)NULL; + + spin_lock(&rdpuart_flock); + list_for_each_safe(ent, n, &rdpuart_families) { + f = list_entry(ent, struct rdpuart_family, family_entry); + if (f->fid == fent->fid) { + list_del(&fent->family_entry); + break; + } + } + + fent->need_exit = 1; + + spin_unlock(&rdpuart_flock); + + while (atomic_read(&(fent->refcnt))) { + printk(KERN_INFO "Waiting for family %u to become free: refcnt=%d.\n", fent->fid, atomic_read(&fent->refcnt)); + if (msleep_interruptible(1000)) { + flush_signals(current); + } + } +} + +/* + * Should be called under rdpuart_flock held. + */ +struct rdpuart_family * rdpuart_family_registered(u8 fid) { + struct list_head * ent = (struct list_head *)NULL; + struct list_head * n = (struct list_head *)NULL; + struct rdpuart_family * f = (struct rdpuart_family *)NULL; + int ret = 0; + list_for_each_safe(ent, n, &rdpuart_families) { + f = list_entry(ent, struct rdpuart_family, family_entry); + if (f->fid == fid) { + ret = 1; + break; + } + } + return (ret) ? f : NULL; +} + +void rdpuart_family_put(struct rdpuart_family * f) { + spin_lock(&rdpuart_flock); + __rdpuart_family_put(f); + spin_unlock(&rdpuart_flock); +} + +void __rdpuart_family_put(struct rdpuart_family * f) { + if (atomic_dec_and_test(&f->refcnt)) { + f->need_exit = 1; + } +} + +void rdpuart_family_get(struct rdpuart_family *f) { + spin_lock(&rdpuart_flock); + __rdpuart_family_get(f); + spin_unlock(&rdpuart_flock); +} + +void __rdpuart_family_get(struct rdpuart_family *f) { + smp_mb__before_atomic_inc(); + atomic_inc(&f->refcnt); + smp_mb__after_atomic_inc(); +} + +EXPORT_SYMBOL(rdpuart_family_get); +EXPORT_SYMBOL(rdpuart_family_put); +EXPORT_SYMBOL(rdpuart_family_registered); +EXPORT_SYMBOL(rdpuart_unregister_family); +EXPORT_SYMBOL(rdpuart_register_family); + + +static int cmd_output(struct rdpuart_cmd * rcmd, int memmode) { + int rv = 0; + struct rdpuart_record * rec = NULL; + struct rdpuart_family * f = NULL; + unsigned char * cbuf = (unsigned char *)NULL; + void * data = (void *)NULL; + int len = 0; + rdpuart_netlink_msg msg; + unsigned char cmd = 0x00; + struct rdpuart_port * port = (struct rdpuart_port *)NULL; + int ilen = 0; + int olen = 0; + void * idata = (void *)NULL; + void * odata = (void *)NULL; + uint32_t cmd_idx = 0x00000000; + + if (rcmd == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: rcmd is a NULL pointer", __func__); + rv = -EINVAL; + goto end; + } + else { + port = rcmd->port; + cmd = rcmd->cmd; + ilen = rcmd->ilen; + olen = rcmd->olen; + idata = rcmd->idata; + odata = rcmd->odata; + len = ilen; + data = idata; + cmd_idx = rcmd->cmd_idx; + } + if (port == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: port is a NULL pointer", __func__); + rv = -EINVAL; + goto end; + } + else if (ilen > 0 && idata == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: idata is a NULL pointer", __func__); + rv = -EINVAL; + goto end; + } + else if (olen > 0 && odata == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: odata is a NULL pointer", __func__); + rv = -ENOMEM; + goto end; + } + + DBGLOG(KERN_INFO "INFO\t[%s()]: called (cmd = \"%s\", idata = \"%p\", ilen = \"%d\", odata = \"%p\", olen = \"%d\")", __func__, RDPUARTCMD(cmd), idata, ilen, odata, olen); + + rec = &(port->rec); + + memset(&msg, 0, sizeof(rdpuart_netlink_msg)); + atomic_set(&(rec->refcnt), 0); + init_completion(&(rec->released)); + + spin_lock(&rdpuart_flock); + f = &rdpuart_default_family; + __rdpuart_family_get(f); + rec->family = f; + + msg.type = cmd; + + if (len > 0 && data != NULL) { + msg.len = len + sizeof(uint32_t); + cbuf = (unsigned char *)kzalloc((sizeof(rdpuart_netlink_msg) + len), memmode); + if (cbuf == NULL) { + rv = -ENOMEM; + goto end; + } + else { + rdpuart_netlink_msg * pm = (rdpuart_netlink_msg *)cbuf; + uint32_t * pn = (uint32_t *)(pm+1); + unsigned char * pd = (unsigned char *)(pn+1); + memcpy(pm, &msg, sizeof(rdpuart_netlink_msg)); + memcpy(pn, &cmd_idx, sizeof(uint32_t)); + memcpy(pd, data, len); + } + } + else { + cbuf = (unsigned char *)kzalloc((sizeof(rdpuart_netlink_msg) + sizeof(uint32_t)), memmode); + if (cbuf == NULL) { + rv = -ENOMEM; + goto end; + } + else { + rdpuart_netlink_msg * pm = (rdpuart_netlink_msg *)cbuf; + uint32_t * pn = (uint32_t *)(pm+1); + memcpy(pm, &msg, sizeof(rdpuart_netlink_msg)); + memcpy(pn, &cmd_idx, sizeof(uint32_t)); + } + } + rv = rdpuart_netlink_send(rec, (void *)cbuf, memmode); + spin_unlock(&rdpuart_flock); + if (rv < 0) { + goto unlock; + } + else { + struct rdpuart_cmd * lcmd = (struct rdpuart_cmd *)kzalloc(sizeof(struct rdpuart_cmd), memmode); + if (lcmd == NULL) { + rv = -ENOMEM; + goto unlock; + } + lcmd->cmd = cmd; + lcmd->idata = idata; + lcmd->ilen = ilen; + lcmd->odata = odata; + lcmd->olen = olen; + lcmd->seqid = rv; + lcmd->completed = 0; + lcmd->port = port; + lcmd->rec = rec; + lcmd->cmd_idx = rcmd->cmd_idx; + spin_lock(&rdpuart_cmd_list_flock); + list_add_tail(&(lcmd->list), &rdpuart_pending_cmd_list); + spin_unlock(&rdpuart_cmd_list_flock); + } + + unlock: + if (cbuf != NULL) { + kfree(cbuf); + } + + end: + DBGLOG(KERN_INFO "INFO\t[%s()]: done (rv = \"%d\")", __func__, rv); + return rv; +} + +static struct list_head * cmd_enq(struct rdpuart_cmd * rcmd) { + unsigned long flags; + struct list_head * rv = &rdpuart_outbound_cmd_list; + + spin_lock_irqsave(&rdpuart_cmd_outbound_flock, flags); + + list_add_tail(&(rcmd->list), &rdpuart_outbound_cmd_list); + + spin_unlock_irqrestore(&rdpuart_cmd_outbound_flock, flags); + + return rv; +} + +static struct rdpuart_cmd * cmd_deq(struct rdpuart_cmd ** rcmd) { + unsigned long flags; + struct rdpuart_cmd * cmd = (struct rdpuart_cmd *)NULL; + + spin_lock_irqsave(&rdpuart_cmd_outbound_flock, flags); + + if (!list_empty(&rdpuart_outbound_cmd_list)) { + cmd = list_entry(rdpuart_outbound_cmd_list.next, struct rdpuart_cmd, list); + list_del(&(cmd->list)); + } + if (rcmd != NULL) { + *rcmd = cmd; + } + + spin_unlock_irqrestore(&rdpuart_cmd_outbound_flock, flags); + + return cmd; +} + +static int cmd_process_list(struct list_head * cmdlist) { + int rv = 0; + struct rdpuart_cmd * cmd = (struct rdpuart_cmd *)NULL; + + DBGLOG(KERN_INFO "INFO\t[%s()]: called", __func__); + + do { + cmd_deq(&cmd); + if (cmd != NULL) { + DBGLOG(KERN_INFO "INFO\t[%s()]: outputting RDP command", __func__); + cmd_output(cmd, GFP_KERNEL); + } + } while (cmd != NULL); + + DBGLOG(KERN_INFO "INFO\t[%s()]: done.", __func__); + + return rv; +} + +static int cmd_is_completed(int seqid, struct rdpuart_cmd ** rcmd) { + int rv = 0; + int found = 0; + struct list_head * ent = (struct list_head *)NULL; + struct list_head * n = (struct list_head *)NULL; + struct rdpuart_cmd * cmd = (struct rdpuart_cmd *)NULL; + + //spin_lock(&rdpuart_cmd_list_flock); + /* + * iterate through the queue of issued cmds and check their "completed" + * status. If completed, return "1"; otherwise, return "0". + */ + list_for_each_safe(ent, n, &rdpuart_pending_cmd_list) { + cmd = list_entry(ent, struct rdpuart_cmd, list); + if (cmd->seqid == seqid) { + found = 1; + rv = (cmd->completed > 0) ? 1 : 0; + DBGLOG(KERN_INFO "found --> seqid = %d; rv = %d", seqid, rv); + if (rv > 0) { + if (rcmd != NULL && *rcmd != NULL && cmd != NULL) { + memcpy(*rcmd, cmd, sizeof(struct rdpuart_cmd)); + //if (cmd->olen > 0 && (*rcmd)->olen > 0 && cmd->odata != NULL && (*rcmd)->odata != cmd->odata) { + // memcpy((*rcmd)->odata, cmd->odata, MINVAL((*rcmd)->olen, cmd->olen)); + //} + //memset(&((*rcmd)->list), 0, sizeof(struct list_head)); + } + list_del(ent); + if (cmd != NULL) { + /* + * ensure the data referenced by idata and odata are + * not prematurely freed, because these may be required + * for return-value processing: + */ + cmd->idata = (void *)NULL; + cmd->odata = (void *)NULL; + //memset(cmd, 0, sizeof(struct rdpuart_cmd)); + /* + * nonetheless, aside from the above entries, this "cmd" + * struct itself is no longer needed, so return it to the + * available memory pool: + */ + kfree(cmd); + cmd = (struct rdpuart_cmd *)NULL; + } + } + break; + } + else { + } + } + if (found < 1) { + /* + * if the value of "found" is not set to "1", then no + * list entry having a seqid equal to the input value + * was encountered in the preceding list traversal; + * therefore, return an appropriate error code: + */ + //rv = -1; + DBGLOG(KERN_WARNING "WARN\t[%s()]: found < 1", __func__); + } + + //spin_unlock(&rdpuart_cmd_list_flock); + return rv; +} + +static int cmd_exec(struct rdpuart_port * port, unsigned char cmd, void * idata, int ilen, void * odata, int olen) { + int rv = 0; + int seqid = 0; + int cmd_idx = 0; + int found = 0; + const unsigned int max_timeout = 1800; /* in jiffies: 1 jiffy = 0.004 sec */ + struct rdpuart_cmd * rcmd = (struct rdpuart_cmd *)NULL; + struct rdpuart_cmd * lcmd = (struct rdpuart_cmd *)NULL; + DECLARE_WAITQUEUE(wait, current); + + might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[%s()]: called (cmd = \"%s\", ilen = \"%d\", olen = \"%d\")", __func__, RDPUARTCMD(cmd), ilen, olen); + + spin_lock(&(port->cmd_lock)); + for (cmd_idx = CMD_OFFSET; cmd_idx < CMD_MAX; cmd_idx++) { + if (port->cmd_array[cmd_idx] == 0) { + port->cmd_array[cmd_idx] = 1; + found = 1; + break; + } + } + spin_unlock(&(port->cmd_lock)); + + if (found != 1) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: found != 1", __func__); + rv = -ENOMEM; + goto end; + } + else if (cmd_idx > CMD_MAX || cmd_idx < CMD_OFFSET) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: cmd_idx out of bounds (=\"%d\")", __func__, cmd_idx); + rv = -EINVAL; + goto end; + } + + rcmd = (struct rdpuart_cmd *)kzalloc(sizeof(struct rdpuart_cmd), GFP_KERNEL); + lcmd = (struct rdpuart_cmd *)kzalloc(sizeof(struct rdpuart_cmd), GFP_KERNEL); + + if (rcmd == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: rcmd == NULL", __func__); + rv = -ENOMEM; + goto end; + } + else if (lcmd == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: lcmd == NULL", __func__); + rv = -ENOMEM; + goto end; + } + + lcmd->cmd = cmd; + lcmd->port = port; + lcmd->idata = idata; + lcmd->ilen = ilen; + lcmd->odata = odata; + lcmd->olen = olen; + lcmd->cmd_idx = cmd_idx; + + add_wait_queue(&pending_cmd_reply_waitq, &wait); + seqid = cmd_output(lcmd, GFP_KERNEL); + + wait_event_interruptible_timeout(pending_cmd_reply_waitq, (cmd_is_completed(seqid, &rcmd)), max_timeout); + remove_wait_queue(&pending_cmd_reply_waitq, &wait); + + spin_lock(&(port->cmd_lock)); + port->cmd_array[cmd_idx] = 0; + spin_unlock(&(port->cmd_lock)); + + if (rcmd != NULL && rcmd->olen > 0 && rcmd->odata != NULL && olen > 0 && odata != NULL && odata != rcmd->odata) { + memcpy(odata, rcmd->odata, olen); + //memcpy(odata, rcmd->odata, MINVAL(olen,rcmd->olen)); + //kfree(rcmd->odata); + } + if (rcmd != NULL) { + kfree(rcmd); + } + if (lcmd != NULL) { + kfree(lcmd); + } + + end: + DBGLOG(KERN_INFO "INFO\t[%s()]: done (rv = \"%d\", seqid = \"%d\").", __func__, rv, seqid); + return rv; +} + +static int cmd_send(struct rdpuart_port * port, unsigned char cmd, void * idata, int ilen, void * odata, int olen) { + int rv = 0; + int seqid = 0; + int cmd_idx = 0; + int found = 0; + struct rdpuart_cmd * rcmd = (struct rdpuart_cmd *)NULL; + struct rdpuart_cmd * lcmd = (struct rdpuart_cmd *)NULL; + + might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[%s()]: called (cmd = \"%s\", ilen = \"%d\", olen = \"%d\")", __func__, RDPUARTCMD(cmd), ilen, olen); + + spin_lock(&(port->cmd_lock)); + for (cmd_idx = CMD_OFFSET; cmd_idx < CMD_MAX; cmd_idx++) { + if (port->cmd_array[cmd_idx] == 0) { + port->cmd_array[cmd_idx] = 1; + found = 1; + break; + } + } + spin_unlock(&(port->cmd_lock)); + + if (found != 1) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: found != 1", __func__); + rv = -ENOMEM; + goto end; + } + else if (cmd_idx > CMD_MAX || cmd_idx < CMD_OFFSET) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: cmd_idx out of bounds (=\"%d\")", __func__, cmd_idx); + rv = -EINVAL; + goto end; + } + + rcmd = (struct rdpuart_cmd *)kzalloc(sizeof(struct rdpuart_cmd), GFP_ATOMIC); + lcmd = (struct rdpuart_cmd *)kzalloc(sizeof(struct rdpuart_cmd), GFP_ATOMIC); + + if (rcmd == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: rcmd == NULL", __func__); + rv = -ENOMEM; + goto end; + } + else if (lcmd == NULL) { + DBGLOG(KERN_ERR "ERROR\t[%s()]: lcmd == NULL", __func__); + rv = -ENOMEM; + goto end; + } + + lcmd->cmd = cmd; + lcmd->port = port; + lcmd->idata = idata; + lcmd->ilen = ilen; + lcmd->odata = (void *)vmalloc(olen); + lcmd->olen = olen; + lcmd->cmd_idx = cmd_idx; + + //seqid = cmd_output(lcmd, GFP_ATOMIC); + cmd_enq(lcmd); + + spin_lock(&(port->cmd_lock)); + port->cmd_array[cmd_idx] = 0; + spin_unlock(&(port->cmd_lock)); + + queue_delayed_work(g_cmdq, &g_cmdw, 100); + + end: + DBGLOG(KERN_INFO "INFO\t[%s()]: done (rv = \"%d\", seqid = \"%d\").", __func__, rv, seqid); + return rv; +} + + +/*** + *** Functions for simulating "readb()" and "writeb()" + ***/ + +/* +static unsigned char rdp_readb(unsigned char * loc) { + unsigned char rv = *loc; + + DBGLOG(KERN_INFO "INFO\t[rdp_readb()]: called (loc = \"%p\", rv = [%d == \"%c\"])", loc, rv, ASCIICHR(rv)); + + //cmd_exec(port, RDPUART_READ, (void *)loc, 1, NULL, 0); + + return rv; +} +*/ + +static int rdp_writeb(unsigned char ch, unsigned char * dest) { + int rv = 0; + + *dest = ch; + + DBGLOG(KERN_INFO "INFO\t[rdp_writeb()]: called (dest = \"%p\", *dest = [%d == \"%c\"], ch = [%d == \"%c\"])", dest, *dest, ASCIICHR(*dest), ch, ASCIICHR(ch)); + + //cmd_exec(port, RDPUART_WRITE, (void *)dest, 1, NULL, 0); + + return rv; +} + +#ifdef DOIRQ + +static int rdpuart_request_irq(int irq, irqreturn_t (*isr)(int, void *), int flags, const char * devname, struct uart_port * port) { + int rv = 0; + + if (irq > 0) { + rv = request_irq(irq, isr, flags, devname, port); + } + + return rv; +} + +static void rdpuart_free_irq(int irq, struct uart_port * port) { + if (irq > 0 && port != NULL) { + free_irq(irq, port); + } +} + +#endif + + +/* --------------------------------------------------------------------- + * Core UART driver operations + */ + +static int rdpuart_receive(struct rdpuart_port * iport, int stat, int buflen, char * buf) { + int rv = 1; + char flag = TTY_NORMAL; + unsigned char ch = 0; + struct uart_port * port = &(iport->port); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30) + struct tty_struct * tty = port->state->port.tty; +#else + struct tty_struct * tty = port->info->port.tty; +#endif + + DBGLOG(KERN_INFO "INFO\t[rdpuart_receive()]: called (stat = \"%d\", buflen = \"%d\")", stat, buflen); + + if (stat != 0 && !(stat & (RDPUART_STATUS_RXVALID | RDPUART_STATUS_OVERRUN | RDPUART_STATUS_FRAME))) { + rv = 0; + goto end; + } + + /* stats */ + if (stat & RDPUART_STATUS_RXVALID) { + port->icount.rx++; + if (buflen > 0 && buf != NULL) { + ch = buf[0]; + } + DBGLOG(KERN_INFO "INFO\t[%s()]: ch = %d", __func__, ch); + if (stat & RDPUART_STATUS_PARITY) { + port->icount.parity++; + } + } + + if (stat & RDPUART_STATUS_OVERRUN) { + port->icount.overrun++; + } + + if (stat & RDPUART_STATUS_FRAME) { + port->icount.frame++; + } + + /* drop byte with parity error if IGNPAR specificed */ + if (stat & port->ignore_status_mask & RDPUART_STATUS_PARITY) { + stat &= ~RDPUART_STATUS_RXVALID; + } + + stat &= port->read_status_mask; + + if (stat & RDPUART_STATUS_PARITY) { + flag = TTY_PARITY; + } + + stat &= ~port->ignore_status_mask; + + if (stat & RDPUART_STATUS_RXVALID) { + tty_insert_flip_char(tty, ch, flag); + } + + if (stat & RDPUART_STATUS_FRAME) { + tty_insert_flip_char(tty, 0, TTY_FRAME); + } + + if (stat & RDPUART_STATUS_OVERRUN) { + tty_insert_flip_char(tty, 0, TTY_OVERRUN); + } + + tty_flip_buffer_push(port->state->port.tty); + + end: + return rv; +} + +static int rdpuart_transmit(struct rdpuart_port * iport, int stat) { + int rv = 1; + struct uart_port * port = &(iport->port); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30) + struct circ_buf *xmit = &port->state->xmit; +#else +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27) + struct circ_buf *xmit = &port->info->xmit; +#else + struct circ_buf *xmit = &port->info->xmit; +#endif +#endif + + might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[rdpuart_transmit()]: called (stat = \"%d\")", stat); + + if (stat & RDPUART_STATUS_TXFULL) { + rv = 0; + goto end; + } + + if (port->x_char) { + rdp_writeb(port->x_char, port->membase + RDPUART_TX); + port->x_char = 0; + port->icount.tx++; + rv = 1; + goto end; + } + + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + rv = 0; + goto end; + } + + //rdp_writeb(xmit->buf[xmit->tail], port->membase + RDPUART_TX); + cmd_exec(iport, RDPUART_WRITE, &(xmit->buf[xmit->tail]), 1, NULL, 0); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1); + port->icount.tx++; + + /* wake up */ + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) { + uart_write_wakeup(port); + } + + end: + return rv; +} + +#ifdef DOIRQ +static irqreturn_t rdpuart_isr(int irq, void * dev_id) { + int busy = 0; + struct uart_port * port = dev_id; + + /* DBGLOG(KERN_INFO "INFO\t[rdpuart_isr()]: called (irq = %d)", irq); */ + + do { + int stat = rdp_readb(port->membase + RDPUART_STATUS); + busy = rdpuart_receive(port, stat); + busy |= rdpuart_transmit(port, stat); + } while (busy); + + /* raise_softirq(irq); */ + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30) + tty_flip_buffer_push(port->state->port.tty); +#else + tty_flip_buffer_push(port->info->port.tty); +#endif + + return IRQ_HANDLED; +} +#endif + +static unsigned int rdpuart_tx_empty(struct rdpuart_port * port) { + unsigned int ret = 0; + unsigned char res = 0; + + might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[rdpuart_tx_empty()]: called"); + + cmd_exec(port, RDPUART_TXEMPTY, NULL, 0, &res, sizeof(unsigned char)); + //res = 1; + ret = (res == 1) ? TIOCSER_TEMT : 0; + return ret; +} + +static unsigned int rdpuart_get_mctrl(struct rdpuart_port * port) { + unsigned int rv = 0; + unsigned char status = 0; + + might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[rdpuart_get_mctrl()]: called"); + + //rv = port->mctrl | TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; + //cmd_exec(port, RDPUART_GETMCTRL, NULL, 0, &status, sizeof(status)); + //return rv; + + if (g_already_opened > 0) { + //cmd_exec(port, RDPUART_GETMCTRL, NULL, 0, &status, sizeof(status)); + status |= port->port.mctrl; + if (status & UART_MSR_DCD) { + rv |= TIOCM_CAR; + } + if (status & UART_MSR_RI) { + rv |= TIOCM_RNG; + } + if (status & UART_MSR_DSR) { + rv |= TIOCM_DSR; + } + if (status & UART_MSR_CTS) { + rv |= TIOCM_CTS; + } + } + else { + rv |= TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; + } + //port->port.mctrl = status; + + return rv; +} + +static void rdpuart_set_mctrl(struct rdpuart_port * port, unsigned int mctrl) { + uint8_t mcr = 0x00; + uint32_t omcr = 0x00000000; + //uint16_t omcr = 0x0000; + + DBGLOG(KERN_INFO "INFO\t[rdpuart_set_mctrl()]: called (mctrl = \"0x%8.8x\")", mctrl); + + if (mctrl & TIOCM_RTS) { + mcr |= UART_MCR_RTS; + } + if (mctrl & TIOCM_DTR) { + mcr |= UART_MCR_DTR; + } + if (mctrl & TIOCM_LOOP) { + mcr |= UART_MCR_LOOP; + } + + omcr |= mcr; + port->port.mctrl = 0; + port->port.mctrl |= mctrl; + + if (g_already_opened > 0) { + //might_sleep(); + //cmd_exec(port, RDPUART_SETMCTRL, &(omcr), sizeof(omcr), NULL, 0); + //cmd_exec(port, RDPUART_SETMCTRL, &(mcr), sizeof(mcr), NULL, 0); + //cmd_send(port, RDPUART_SETMCTRL, &(mcr), sizeof(mcr), NULL, 0); + cmd_send(port, RDPUART_SETMCTRL, &(mcr), sizeof(mcr), NULL, 0); + } +} + +static void rdpuart_stop_tx(struct rdpuart_port * port) { + + DBGLOG(KERN_INFO "INFO\t[rdpuart_stop_tx()]: called"); + + //cmd_exec(port, RDPUART_TXSTOP, NULL, 0, NULL, 0); +} + +static void rdpuart_start_tx(struct rdpuart_port * port) { + + DBGLOG(KERN_INFO "INFO\t[rdpuart_start_tx()]: called"); + + //rdpuart_transmit(port, rdp_readb(port->membase + RDPUART_STATUS)); + //cmd_exec(port, RDPUART_TXSTART, NULL, 0, NULL, 0); + + rdpuart_transmit(port, 0); +} + +static void rdpuart_stop_rx(struct rdpuart_port * port) { + + DBGLOG(KERN_INFO "INFO\t[rdpuart_stop_rx()]: called"); + + /* don't forward any more data (like !CREAD) */ + port->port.ignore_status_mask = RDPUART_STATUS_RXVALID | RDPUART_STATUS_PARITY + | RDPUART_STATUS_FRAME | RDPUART_STATUS_OVERRUN; + + //cmd_exec(port, RDPUART_RXSTOP, NULL, 0, NULL, 0); +} + +static void rdpuart_enable_ms(struct rdpuart_port * port) { + + might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[rdpuart_enable_ms()]: called"); + + cmd_exec(port, RDPUART_MSENABLE, NULL, 0, NULL, 0); + /* N/A */ +} + +static void rdpuart_break_ctl(struct rdpuart_port * port, int ctl) { + + might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[rdpuart_break_ctl()]: called (ctl = \"%d\")", ctl); + + cmd_exec(port, RDPUART_BREAKCTL, NULL, 0, NULL, 0); + /* N/A */ +} + +static int rdpuart_startup(struct rdpuart_port * port) { + int rv = 0; + uint32_t fd = 0x00000000; + + might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[rdpuart_startup()]: called"); + + //if (!(ret = rdpuart_request_irq(port->irq, rdpuart_isr, IRQF_DISABLED | IRQF_SAMPLE_RANDOM, title, port))) { + //rdp_writeb(RDPUART_CONTROL_RST_RX | RDPUART_CONTROL_RST_TX, port->membase + RDPUART_CONTROL); + //rdp_writeb(RDPUART_CONTROL_IE, port->membase + RDPUART_CONTROL); + //} + + //DBGLOG(KERN_INFO "INFO\t[rdpuart_startup()]: ret = \"%d\"", ret); + + cmd_exec(port, RDPUART_OPEN, NULL, 0, &fd, sizeof(fd)); + //if (fd > 0) { + g_already_opened++; + //} + + if (g_already_opened == 1) { + g_stop = 0; + cmd_exec(port, RDPUART_START, NULL, 0, NULL, 0); + } + + DBGLOG(KERN_INFO "INFO\t[%s()]: done (fd = %d).", __func__, fd); + return rv; +} + +static void rdpuart_shutdown(struct rdpuart_port * port) { + + might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[rdpuart_shutdown()]: called"); + + if (g_already_opened == 1) { + g_stop = 1; + cmd_exec(port, RDPUART_STOP, NULL, 0, NULL, 0); + } + + cmd_exec(port, RDPUART_CLOSE, NULL, 0, NULL, 0); + g_already_opened--; +} + +static void rdpuart_set_termios(struct rdpuart_port * port, struct ktermios * termios, struct ktermios * old) { + unsigned long flags = 0; + unsigned int baud = 0; + + DBGLOG(KERN_INFO "INFO\t[rdpuart_set_termios()]: called"); + + spin_lock_irqsave(&(port->port.lock), flags); + + port->port.read_status_mask = RDPUART_STATUS_RXVALID | RDPUART_STATUS_OVERRUN + | RDPUART_STATUS_TXFULL; + + if (termios->c_iflag & INPCK) { + port->port.read_status_mask |= + RDPUART_STATUS_PARITY | RDPUART_STATUS_FRAME; + } + + port->port.ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) { + port->port.ignore_status_mask |= RDPUART_STATUS_PARITY + | RDPUART_STATUS_FRAME | RDPUART_STATUS_OVERRUN; + } + + /* ignore all characters if CREAD is not set */ + if ((termios->c_cflag & CREAD) == 0) { + port->port.ignore_status_mask |= + RDPUART_STATUS_RXVALID | RDPUART_STATUS_PARITY + | RDPUART_STATUS_FRAME | RDPUART_STATUS_OVERRUN; + } + + /* update timeout */ + baud = uart_get_baud_rate(&(port->port), termios, old, 0, 460800); + uart_update_timeout(&(port->port), termios->c_cflag, baud); + + spin_unlock_irqrestore(&(port->port.lock), flags); +} + +static const char * rdpuart_type(struct rdpuart_port * port) { + const char * rv = title; + + DBGLOG(KERN_INFO "INFO\t[rdpuart_type()]: called"); + + return (port->port.type == PORT_RDP) ? rv : NULL; +} + +static void rdpuart_release_port(struct rdpuart_port * port) { + + DBGLOG(KERN_INFO "INFO\t[rdpuart_release_port()]: called"); + + port->port.membase = NULL; +} + +static int rdpuart_request_port(struct rdpuart_port * port) { + int rv = 0; + + DBGLOG(KERN_INFO "INFO\t[rdpuart_request_port()]: port=%p; port->mapbase=%llx", port, (unsigned long long) port->port.mapbase); + + port->port.membase = (void *)port->port.mapbase; + + return rv; +} + +static void rdpuart_config_port(struct rdpuart_port * port, int flags) { + + DBGLOG(KERN_INFO "INFO\t[rdpuart_config_port()]: called (flags = \"0x%8.8x\")", flags); + + if (!rdpuart_request_port(port)) { + port->port.type = PORT_RDP; + } + port->port.flags = flags; +} + +static int rdpuart_verify_port(struct rdpuart_port * port, struct serial_struct * ser) { + + DBGLOG(KERN_INFO "INFO\t[rdpuart_verify_port()]: called"); + + /* we don't want the core code to modify any port params */ + //return -EINVAL; + return 0; +} + +static void rdpuart_send_xchar(struct rdpuart_port * port, char ch) { + + might_sleep(); + + DBGLOG(KERN_INFO "INFO\t[rdpuart_send_xchar()]: called; ch = \"%c\" (%d)", ASCIICHR(ch), ch); + + cmd_exec(port, RDPUART_XCHAR, NULL, 0, NULL, 0); +} + +/* +static int rdpuart_ioctl(struct rdpuart_port * port, unsigned int ioctl, unsigned long dp) { + int rv = 0; + void * rp = (void *)NULL; + void * iarg = (void *)NULL; + int rlen = 0; + int ilen = 0; + char * cname = (char *)NULL; + + switch (ioctl) { + case TCGETS: + { + struct termios * argp = (struct termios *)dp; + ilen = sizeof(struct termios); + iarg = (void *)argp; + cname = "TCGETS"; + } + break; + case TCSETS: + { + const struct termios * argp = (const struct termios *)dp; + ilen = sizeof(struct termios); + iarg = (void *)argp; + cname = "TCSETS"; + } + break; + case TCSETSW: + { + const struct termios * argp = (const struct termios *)dp; + ilen = sizeof(struct termios); + iarg = (void *)argp; + cname = "TCSETSW"; + } + break; + case TCSETSF: + { + const struct termios * argp = (const struct termios *)dp; + ilen = sizeof(struct termios); + iarg = (void *)argp; + cname = "TCSETSF"; + } + break; + case TCGETA: + { + struct termio * argp = (struct termio *)dp; + ilen = sizeof(struct termio); + iarg = (void *)argp; + cname = "TCGETA"; + } + break; + case TCSETA: + { + const struct termio * argp = (const struct termio *)dp; + ilen = sizeof(struct termio); + iarg = (void *)argp; + cname = "TCSETA"; + } + break; + case TCSETAW: + { + const struct termio * argp = (const struct termio *)dp; + ilen = sizeof(struct termio); + iarg = (void *)argp; + cname = "TCSETAW"; + } + break; + case TCSETAF: + { + const struct termio * argp = (const struct termio *)dp; + ilen = sizeof(struct termio); + iarg = (void *)argp; + cname = "TCSETAF"; + } + break; + case TIOCGLCKTRMIOS: + { + struct termios * argp = (struct termios *)dp; + ilen = sizeof(struct termios); + iarg = (void *)argp; + cname = "TIOCGLCKTRMIOS"; + } + break; + case TIOCSLCKTRMIOS: + { + const struct termios * argp = (const struct termios *)dp; + ilen = sizeof(struct termios); + iarg = (void *)argp; + cname = "TIOCSLCKTRMIOS"; + } + break; + case TIOCGWINSZ: + { + struct winsize * argp = (struct winsize *)dp; + ilen = sizeof(struct winsize); + iarg = (void *)argp; + cname = "TIOCGWINSZ"; + } + break; + case TIOCSWINSZ: + { + const struct winsize * argp = (const struct winsize *)dp; + ilen = sizeof(struct winsize); + iarg = (void *)argp; + cname = "TIOCSWINSZ"; + } + break; + case TCSBRK: + { + int arg = *((int *)dp); + ilen = sizeof(int); + iarg = (void *)&arg; + cname = "TCSBRK"; + } + break; + case TCSBRKP: + { + int arg = *((int *)dp); + ilen = sizeof(int); + iarg = (void *)&arg; + cname = "TCSBRKP"; + } + break; + case TIOCSBRK: + { + ilen = 0; + iarg = iarg; + cname = "TIOCSBRK"; + } + break; + case TIOCCBRK: + { + ilen = 0; + iarg = iarg; + cname = "TIOCCBRK"; + } + break; + case FIONREAD: + { + int * argp = (int *)dp; + ilen = sizeof(int *); + iarg = (void *)argp; + cname = "FIONREAD"; + } + break; + case TIOCOUTQ: + { + int * argp = (int *)dp; + ilen = sizeof(int *); + iarg = (void *)argp; + cname = "TIOCOUTQ"; + } + break; + case TCFLSH: + { + int arg = *((int *)dp); + ilen = sizeof(int); + iarg = (void *)&arg; + cname = "TCFLSH"; + } + break; + case TIOCSTI: + { + const char * argp = (const char *)dp; + ilen = sizeof(char); + iarg = (void *)argp; + cname = "TIOCSTI"; + } + break; + case TIOCCONS: + { + ilen = 0; + iarg = iarg; + cname = "TIOCCONS"; + } + break; + case TIOCGETD: + { + int * argp = (int *)dp; + ilen = sizeof(int *); + iarg = (void *)argp; + cname = "TIOCGETD"; + } + break; + case TIOCSETD: + { + const int * argp = (const int *)dp; + ilen = sizeof(int *); + iarg = (void *)argp; + cname = "TIOCSETD"; + } + break; + case TIOCPKT: + { + ilen = 0; + iarg = iarg; + rv = -ENOTTY; + cname = "TIOCPKT"; + } + break; + default: + { + cname = "(none)"; + } + break; + } + + DBGLOG(KERN_INFO "INFO\t[rdpuart_ioctl()]: called (cmd = \"%s\")", cname); + + ilen = ilen; + rlen = rlen; + rp = rp; + + return rv; +} + +*/ + +static const rdpuart_ops_t l_rdpuart_ops = { + .tx_empty = rdpuart_tx_empty, + .set_mctrl = rdpuart_set_mctrl, + .get_mctrl = rdpuart_get_mctrl, + .stop_tx = rdpuart_stop_tx, + .start_tx = rdpuart_start_tx, + .send_xchar = rdpuart_send_xchar, + .stop_rx = rdpuart_stop_rx, + .enable_ms = rdpuart_enable_ms, + .break_ctl = rdpuart_break_ctl, + .startup = rdpuart_startup, + .shutdown = rdpuart_shutdown, + .set_termios = rdpuart_set_termios, + .type = rdpuart_type, + .release_port = rdpuart_release_port, +// .request_port = rdpuart_request_port, + .config_port = rdpuart_config_port, + .verify_port = rdpuart_verify_port, +// .ioctl = rdpuart_ioctl, +}; + +static const struct uart_ops * rdpuart_ops = (const struct uart_ops *)&l_rdpuart_ops; + +static struct uart_driver rdpuart_uart_driver = { + .owner = THIS_MODULE, + .driver_name = RDPUART_TITLE, + .dev_name = RDPUART_NAME, + .major = RDPUART_MAJOR, + .minor = RDPUART_MINOR, + .nr = RDPUART_NR_UARTS, +}; + +/* --------------------------------------------------------------------- + * Port assignment functions (mapping devices to uart_port structures) + */ + +/** rdpuart_assign: register a rdpuart device with the driver + * + * @dev: pointer to device structure + * @id: requested id number. Pass -1 for automatic port assignment + * @base: base address of rdpuart registers + * @irq: irq number for rdpuart + * @device_id: unique identifier for this port, provided by the RDP client + * + * Returns: 0 on success, < 0 otherwise + */ +static int __devinit rdpuart_assign(struct device * dev, int id, resource_size_t base, resource_size_t irq, uint32_t device_id) { + int rv = 0; + struct rdpuart_port * up = (struct rdpuart_port *)NULL; + struct uart_port * port = (struct uart_port *)NULL; + struct rdpuart_record * rec = (struct rdpuart_record *)NULL; + struct device * odev = dev; + + /* if id = -1; then scan for a free id and use that */ + if (id < 0) { + for (id = 0; id < nr; id++) { + if (rdpuart_ports[id].port.mapbase == 0) { + break; + } + } + } + if (id >= nr) { + dev_err(dev, "%s%i too large", name, id); + DBGLOG(KERN_ERR "ERROR\t[rdpuart_assign()]: \"%s%i\" exceeds the maximum number of UARTs for this device (RDPUART_NR_UARTS = \"%d\")", name, id, nr); + return -EINVAL; + } + if (id < 0) { + dev_err(dev, "\"%s\": invalid id (%i)", name, id); + DBGLOG(KERN_ERR "ERROR\t[rdpuart_assign()]: invalid port id \"%i\"", id); + return -EINVAL; + } + if ((rdpuart_ports[id].port.mapbase) && (rdpuart_ports[id].port.mapbase != base)) { + dev_err(dev, "cannot assign to %s%i; it is already in use", name, id); + DBGLOG(KERN_ERR "ERROR\t[rdpuart_assign()]: cannot assign to \"%s%i\" (already in use)", name, id); + return -EBUSY; + } + + up = &(rdpuart_ports[id]); + memset((up->cmd_array), 0, sizeof(up->cmd_array)); + spin_lock_init(&(up->cmd_lock)); + + port = &(rdpuart_ports[id].port); + g_port = port; + + up->device_id = device_id; + + spin_lock_init(&(port->lock)); + //port->fifosize = 16; + port->regshift = 2; + port->iotype = UPIO_MEM; + port->iobase = 1; /* mark port as being in use */ + port->mapbase = base; + port->membase = NULL; + port->ops = rdpuart_ops; + port->irq = irq; + port->dev = dev; + //port->flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; + //port->type = PORT_UNKNOWN; + port->type = PORT_RDPUART; + port->line = id; + port->uartclk = 9600 * 16; + + dev_set_drvdata(dev, port); + + /* Register the port */ + DBGLOG(KERN_INFO "INFO\t[%s()]: about to call uart_add_one_port()...", __func__); + rv = uart_add_one_port(&rdpuart_uart_driver, port); + if (rv) { + dev_err(dev, "ERROR\t[rdpuart_assign()]: uart_add_one_port() failed; (err=\"%i\")", rv); + DBGLOG(KERN_ERR "ERROR\t[rdpuart_assign()]: uart_add_one_port() failed (err=\"%i\")", rv); + port->mapbase = 0; + dev_set_drvdata(dev, NULL); + } + else { + rec = &(rdpuart_ports[id].rec); + memset(rec, 0, sizeof(struct rdpuart_record)); + spin_lock_init(&(rec->lock)); + rec->owner = THIS_MODULE; + rec->id = id; + rec->initialized = 1; + memcpy(&(rec->dev), odev, sizeof(struct device)); + rec->driver = rec->dev.driver; + rec->seq = 1; + snprintf(rec->name, (RDPUART_MAXNAMELEN - 1), "%s%d", title, rec->id); + rec->port = port; + } + + return rv; +} + +/** rdpuart_release: unregister a rdpuart device from a driver + * + * @dev: pointer to device structure + */ +static int __devexit rdpuart_release(struct device * dev) { + int rc = 0; + struct rdpuart_port * port = (struct rdpuart_port *)NULL; + port = (struct rdpuart_port *)(dev_get_drvdata(dev)); + if (port) { + rc = uart_remove_one_port(&rdpuart_uart_driver, &(port->port)); + dev_set_drvdata(dev, NULL); + port->port.mapbase = 0; + } + return rc; +} + +/* --------------------------------------------------------------------- + * Platform bus binding + */ + +static int __devinit rdpuart_probe(struct platform_device * pdev) { + int rv = 0; + struct resource * mem = (struct resource *)NULL; + struct resource * irq = (struct resource *)NULL; + + if (pdev != NULL && pdev->name != NULL) { + DBGLOG(KERN_INFO "INFO\t[rdpuart_probe()]: called (pdev->name = \"%s\")", pdev->name); + } + + if (pdev == NULL) { + rv = -EINVAL; + DBGLOG(KERN_ERR "ERROR\t[rdpuart_probe()]: pdev is a null pointer"); + goto end; + } + else if (!(mem = platform_get_resource(pdev, IORESOURCE_MEM, 0))) { + rv = -ENODEV; + DBGLOG(KERN_ERR "ERROR\t[rdpuart_probe()]: failed to assign iomem"); + goto end; + } + else if (!(irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0))) { + rv = -ENODEV; + DBGLOG(KERN_ERR "ERROR\t[rdpuart_probe()]: failed to assign irq"); + goto end; + } + else if ((rv = rdpuart_assign(&(pdev->dev), pdev->id, mem->start, irq->start, 0)) < 0) { + DBGLOG(KERN_ERR "ERROR\t[rdpuart_probe()]: rdpuart_assign() returned error code \"%d\"", rv); + } + + end: + DBGLOG(KERN_INFO "INFO\t[rdpuart_probe()]: done."); + return rv; +} + +static int __devexit rdpuart_remove(struct platform_device * pdev) { + return rdpuart_release(&(pdev->dev)); +} + + +/* --------------------------------------------------------------------- + * RDP command work queue handler + */ +static void rdpuart_cmdw_handler(struct work_struct * work) { + if (g_exit == 0) { + cmd_process_list(&rdpuart_outbound_cmd_list); + } +} + + +/* --------------------------------------------------------------------- + * Module setup/teardown + */ +int __init rdpuart_init(void) { + int ret = 0; + + struct resource * iomem = (struct resource *)NULL; + struct resource * irq = (struct resource *)NULL; + struct resource rarr[2]; + + rdpuart_platform_driver.driver.name = title; + rdpuart_uart_driver.driver_name = title; + rdpuart_uart_driver.dev_name = name; + rdpuart_uart_driver.major = major; + rdpuart_uart_driver.minor = minor; + rdpuart_uart_driver.nr = nr; + + memset(rdpuart_ports, 0, sizeof(rdpuart_ports)); + memset(rarr,0,sizeof(struct resource)*2); + if (rarr == NULL) { + ret = -ENOMEM; + goto err_uart; + } + else { + resource_size_t start = 0; + resource_size_t end = 0; + void * membuf = (void *)NULL; +#if PAGE_SIZE > 3999 + membuf = (void *)get_zeroed_page(GFP_KERNEL); + start = (resource_size_t)membuf; + end = (resource_size_t)(membuf + PAGE_SIZE); +#else + membuf = kzalloc(4000, GFP_KERNEL); + start = (resource_size_t)membuf; + end = (resource_size_t)(membuf + 4000); +#endif + { + struct resource liomem = { + .start = start, + .end = end, + .flags = IORESOURCE_MEM, + }; + struct resource lirq = { + .start = (resource_size_t)RDPUART_NR_IRQ, + .end = (resource_size_t)RDPUART_NR_IRQ, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE, + }; + iomem = &(rarr[0]); + irq = &(rarr[1]); + memcpy(iomem,&liomem,sizeof(struct resource)); + memcpy(irq,&lirq,sizeof(struct resource)); + } + } + + g_cmdq = create_singlethread_workqueue(Q_NAME); + //queue_delayed_work(g_cmdq, &g_cmdw, 100); + + DBGLOG(KERN_INFO "INFO\t[rdpuart_init()]: calling uart_register_driver()"); + if ((ret = uart_register_driver(&rdpuart_uart_driver))) { + goto err_uart; + } + + DBGLOG(KERN_INFO "INFO\t[rdpuart_init()]: calling platform_driver_register() {rdpuart_platform_driver.driver.bus = \"%p\"}",rdpuart_platform_driver.driver.bus); + if ((ret = platform_driver_register(&rdpuart_platform_driver))) { + goto err_plat; + } + + if (1==2) + { + struct resource * tarr = (struct resource *)NULL; + DBGLOG(KERN_INFO "INFO\t[rdpuart_init()]: calling platform_device_register_simple() {rdpuart_platform_driver.driver.bus = \"%p\"}",rdpuart_platform_driver.driver.bus); + tarr = (struct resource *)kzalloc(sizeof(rarr), GFP_KERNEL); + memcpy(tarr,rarr,sizeof(rarr)); + if (!(gdev = platform_device_register_simple(title, -1, tarr, ARRAY_SIZE(rarr)))) { + ret = -ENODEV; + goto err_plat; + } + } + + rdpuart_init_netlink(); + + return ret; + +err_plat: + uart_unregister_driver(&rdpuart_uart_driver); +err_uart: + DBGLOG(KERN_ERR "registering rdpuart driver failed: err=%d", ret); + return ret; +} + +void __exit rdpuart_exit(void) { + g_exit = 1; + flush_workqueue(g_cmdq); + cancel_delayed_work(&g_cmdw); + destroy_workqueue(g_cmdq); + rdpuart_stop_netlink(); + if (gdev != NULL) { + platform_device_unregister(gdev); + } + platform_driver_unregister(&rdpuart_platform_driver); + uart_unregister_driver(&rdpuart_uart_driver); +} + +module_init(rdpuart_init); +module_exit(rdpuart_exit); + +MODULE_AUTHOR("Ryan Rafferty "); +MODULE_DESCRIPTION("Virtual serial port driver for RDP"); +MODULE_LICENSE("GPL"); + +/* work with hotplug and coldplug */ +/* M ODULE_ALIAS(R DPUART_ALIAS); */ diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/linux/include/linux/rdp.h posixrdp/posixxrdp.orig/linux/include/linux/rdp.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/linux/include/linux/rdp.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/linux/include/linux/rdp.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,448 @@ +/* + * + */ + +#ifndef LINUX_RDP_H +#define LINUX_RDP_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* #define PORT_RDP PORT_UNKNOWN */ +/* #define PORT_RDP PORT_16550A */ +/* #define PORT_RDP PORT_8250 */ +#define PORT_RDP PORT_UARTLITE +#define RDP_MAXNAMELEN 32 + +#define CN_IDX_RDP CN_IDX_CIFS + 0x10 +#define CN_VAL_RDP CN_VAL_CIFS + 0x10 +#define RDP_FAMILY_DEFAULT 0 +#define RDP_NETLINK_MSG_MAXSIZE 12000 + +#define RDP_NETLINK_DRIVER_BASE 0x0000deef +#define RDP_NETLINK_CLIENT_BASE 0xfeed0000 + +#ifndef MINVAL +#define MINVAL(x,y) (((x) > (y)) ? (y) : (x)) +#endif + +#define ASCIICHR(x) (((x) > 31 && x < 127) ? x : 0x20) +#define DBGLOG(...) { \ + printk(__VA_ARGS__); \ + printk("\n"); \ +} +#define RDPCMD(x) (cmdarray[(x & 0x1f)]) + +#define RDP_MAGIC 0xabee + +typedef struct _rdp_data { + /* Per-device data */ + + /* The RDP device id for this */ + /* redirected serial port: */ + uint32_t device_id; + + /* The file handle of the AF_NETLINK device */ + /* for communicating with userspace: */ + int netlink_fh; + +} rdp_data; + +enum rdp_netlink_message_types { + RDP_PING = 0x00, + RDP_IOCTL = 0x01, + RDP_SETMCTRL = 0x02, + RDP_GETMCTRL = 0x03, + RDP_GETSTATUS = 0x04, + RDP_ADDPORT = 0x05, + RDP_OPEN = 0x06, + RDP_CLOSE = 0x07, + RDP_READ = 0x08, + RDP_WRITE = 0x09, + RDP_DATA = 0x0A, + RDP_START = 0x0B, + RDP_STOP = 0x0C, + RDP_GETBAUD = 0x0D, + RDP_SETBAUD = 0x0E, + RDP_TXEMPTY = 0x0F, + RDP_TXFULL = 0x10, + RDP_TXSTOP = 0x11, + RDP_TXSTART = 0x12, + RDP_RXEMPTY = 0x13, + RDP_RXFULL = 0x14, + RDP_RXSTOP = 0x15, + RDP_RXSTART = 0x16, + RDP_MSENABLE = 0x17, + RDP_BREAKCTL = 0x18, + RDP_SETTERMIOS = 0x19, + RDP_GETTERMIOS = 0x1A, + RDP_XCHAR = 0x1B, + RDP_ASYNC = 0x40, + RDP_REPLY = 0x80, +}; + +#define CMD_TO_STRING_ARRAY_DEF { \ + [0x00] = "RDP_PING", \ + [0x01] = "RDP_IOCTL", \ + [0x02] = "RDP_SETMCTRL", \ + [0x03] = "RDP_GETMCTRL", \ + [0x04] = "RDP_GETSTATUS", \ + [0x05] = "RDP_ADDPORT", \ + [0x06] = "RDP_OPEN", \ + [0x07] = "RDP_CLOSE", \ + [0x08] = "RDP_READ", \ + [0x09] = "RDP_WRITE", \ + [0x0A] = "RDP_DATA", \ + [0x0B] = "RDP_START", \ + [0x0C] = "RDP_STOP", \ + [0x0D] = "RDP_GETBAUD", \ + [0x0E] = "RDP_SETBAUD", \ + [0x0F] = "RDP_TXEMPTY", \ + [0x10] = "RDP_TXFULL", \ + [0x11] = "RDP_TXSTOP", \ + [0x12] = "RDP_TXSTART", \ + [0x13] = "RDP_RXEMPTY", \ + [0x14] = "RDP_RXFULL", \ + [0x15] = "RDP_RXSTOP", \ + [0x16] = "RDP_RXSTART", \ + [0x17] = "RDP_MSENABLE", \ + [0x18] = "RDP_BREAKCTL", \ + [0x19] = "RDP_SETTERMIOS", \ + [0x1A] = "RDP_GETTERMIOS", \ + [0x1B] = "RDP_XCHAR", \ + [0x40] = "RDP_ASYNC", \ + [0x80] = "RDP_REPLY", \ +} + +typedef struct rdp_irq_data { + uint32_t device_id; + uint32_t mask; + uint8_t dtr; + uint8_t rts; + uint8_t cd; + uint8_t ri; + uint32_t mcr; + uint32_t msr; + uint32_t status; + uint32_t rx_len; + uint8_t rx_buf[0]; +} rdp_irq_data_t; + +typedef struct rdp_irq_entry { + struct rdp_port * port; + struct rdp_irq_data * data; + struct list_head list; +} rdp_irq_entry_t; + +typedef struct rdp_write_entry { + struct rdp_port * port; + struct list_head list; + spinlock_t lock; + struct completion done; + unsigned char completed; + unsigned char canceled; + int rv; + int len; + unsigned char * data; +} rdp_write_entry_t; + +#ifndef __KERNEL__ + +typedef struct _rdp_netlink_msg { + uint8_t type; + uint8_t reserved; + uint16_t len; + union { + uint8_t id[8]; + struct rdp_mst { + uint32_t id; + uint32_t res; + } mst; + } id; + uint8_t data[0]; +} rdp_netlink_msg; + + +typedef struct _rdp_reg_num { +#if defined(__LITTLE_ENDIAN_BITFIELD) + uint64_t family:8; + uint64_t id:48; + uint64_t crc:8; +#elif defined(__BIG_ENDIAN_BITFIELD) + uint64_t crc:8; + uint64_t id:48; + uint64_t family:8; +#else +#error "Please fix " +#endif +} rdp_reg_num; + +#endif + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include +#include + + +typedef struct _rdp_reg_num { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u64 family:8, + id:48, + crc:8; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u64 crc:8, + id:48, + family:8; +#else +#error "Please fix " +#endif +} rdp_reg_num; + + +/*** + *** Netlink/Connection ("cn") definitions + ***/ + +typedef struct rdp_record { + struct rdp_port * port; + struct tty_struct * tty; + struct module * owner; + char name[RDP_MAXNAMELEN]; + unsigned long attempts; + int initialized; + u32 id; + int search_count; + atomic_t refcnt; + void * priv; + ssize_t priv_size; + long flags; + struct task_struct * thread; + struct semaphore mutex; + struct device_driver * driver; + struct device dev; + spinlock_t lock; + u32 seq; + struct rdp_family * family; + void * family_data; + struct completion released; + struct list_head list; +} rdp_record_t; + +typedef struct _rdp_netlink_msg { + __u8 type; + __u8 reserved; + __u16 len; + union { + __u8 id[8]; + struct rdp_mst { + __u32 id; + __u32 res; + } mst; + } id; + __u8 data[0]; +} rdp_netlink_msg; + +#ifndef __RDP_FAMILY_H +#define __RDP_FAMILY_H + +#include +#include +#include + +#define MAXNAMELEN 32 + +struct rdp_family_ops { + int (* op)(struct rdp_record *); +}; + +struct rdp_family { + struct list_head family_entry; + u8 fid; + + struct rdp_family_ops * fops; + + atomic_t refcnt; + u8 need_exit; + spinlock_t lock; +}; + +void rdp_family_get(struct rdp_family *); +void rdp_family_put(struct rdp_family *); +struct rdp_family * rdp_family_registered(u8); +void rdp_unregister_family(struct rdp_family *); +int rdp_register_family(struct rdp_family *); + +#endif /* __RDP_FAMILY_H */ + + +typedef struct rdp_tty { + struct tty_driver * driver; + struct list_head list; + #define RDP_STATUS_NORMAL 0x00 + #define RDP_STATUS_EXIT 0x01 + #define RDP_STATUS_LOADING 0x02 + #define RDP_STATUS_CLOSING 0x04 + #define RDP_STATUS_ERROR 0x08 + atomic_t status; + //unsigned char status; + struct mutex mut; +} rdp_tty_t; + +typedef struct rdp_cmd { + unsigned char cmd; + void * idata; + int ilen; + void * odata; + int olen; + + spinlock_t lock; + int seqid; + atomic_t completed; + struct list_head list; + + struct rdp_record * rec; + struct rdp_port * port; + struct tty_struct * tty; + + int cmd_idx; + struct completion * done; + + void * aux; +} rdp_cmd_t; + + +typedef struct completed_cmd_list { + struct rdp_cmd * cmd; + struct list_head list; +} completed_cmd_list_t; + + +typedef struct rdp_port { + #define MAX_PORT 4 + #define CMD_MAX 32 + #define CMD_OFFSET 4 + struct tty_port port; + struct rdp_record rec; + struct tty_struct * tty; + struct list_head list; + unsigned char initialized; + int g_ports_index; + atomic_t open_count; + uint32_t device_id; + spinlock_t cmd_lock; + int cmd_array[CMD_MAX]; + spinlock_t status_lock; + struct mutex mut; + struct file * fp; + int msr; /* MSR shadow */ + int mcr; /* MCR shadow */ + int flags; /* defined in tty.h */ + int baud; + int x_char; + wait_queue_head_t wait; + struct async_icount icount; + struct circ_buf xmit; + int blocked_open; + wait_queue_head_t open_wait; + wait_queue_head_t close_wait; + struct serial_struct serial; +} rdp_port_t; + + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30) +# define CBARGS struct cn_msg * imsg, struct netlink_skb_parms * parms +#else +# define CBARGS void * imsg +#endif + +typedef struct rdp_cb_entry { + struct list_head list; + struct netlink_skb_parms parms; + struct cn_msg imsg; +} rdp_cb_entry_t; + + +#endif /* __KERNEL__ */ + +#ifndef WIN32_SERIAL + +#define MAX_BAUD_RATE 460800 +#define MAX_BAUD_REMAINDER 4608 + +#define DIV_LATCH_LS 0x00 +#define XMT_HOLD_REGISTER 0x00 +#define XVR_BUFFER_REGISTER 0x00 +#define DIV_LATCH_MS 0x01 +#define FIFO_CONTROL_REGISTER 0x02 +#define LINE_CONTROL_REGISTER 0x03 +#define MODEM_CONTROL_REGISTER 0x04 +#define LINE_STATUS_REGISTER 0x05 +#define MODEM_STATUS_REGISTER 0x06 + +#define SERIAL_MCR_DTR 0x01 +#define SERIAL_MCR_RTS 0x02 +#define SERIAL_MCR_LOOP 0x10 + +#define SERIAL_MSR_CTS 0x10 +#define SERIAL_MSR_CD 0x80 +#define SERIAL_MSR_RI 0x40 +#define SERIAL_MSR_DSR 0x20 +#define SERIAL_MSR_MASK 0xf0 + +#define SERIAL_8_DATA 0x03 +#define SERIAL_7_DATA 0x02 +#define SERIAL_6_DATA 0x01 +#define SERIAL_5_DATA 0x00 + +#define SERIAL_ODD_PARITY 0X08 +#define SERIAL_EVEN_PARITY 0X18 +#define SERIAL_TWO_STOPB 0x04 +#define SERIAL_ONE_STOPB 0x00 + +#define DEFAULT_DIVISOR 0x30 /* gives 9600 baud rate */ +#define DEFAULT_LCR SERIAL_8_DATA /* 8, none , 1 */ + +#define SERIAL_LSR_OE 0x02 +#define SERIAL_LSR_PE 0x04 +#define SERIAL_LSR_FE 0x08 +#define SERIAL_LSR_BI 0x10 + +#define SERIAL_MSR_CTS 0x10 +#define SERIAL_MSR_CD 0x80 +#define SERIAL_MSR_RI 0x40 +#define SERIAL_MSR_DSR 0x20 +#define SERIAL_MSR_MASK 0xf0 + +#define LOOPMODE_BITS 0x41 /* LOOP1 = b6, LOOP0 = b0 (PORT B) */ +#define ALL_LOOPBACK 0x01 +#define MODEM_CTRL 0x40 +#define RS232_MODE 0x00 + +#endif + +#endif /* LINUX_RDP_H */ diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/linux/include/linux/rdptty.h posixrdp/posixxrdp.orig/linux/include/linux/rdptty.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/linux/include/linux/rdptty.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/linux/include/linux/rdptty.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,327 @@ +/* + * + */ + +#ifndef LINUX_RDPTTY_H +#define LINUX_RDPTTY_H + +#include + +/* #define PORT_RDP PORT_UNKNOWN */ +/* #define PORT_RDP PORT_16550A */ +/* #define PORT_RDP PORT_8250 */ +#define PORT_RDP PORT_UARTLITE +#define PORT_RDPTTY PORT_RDP +#define RDPTTY_MAXNAMELEN 32 + +#define CN_IDX_RDPTTY CN_IDX_CIFS + 0x10 +#define CN_VAL_RDPTTY CN_VAL_CIFS + 0x10 +#define RDPTTY_FAMILY_DEFAULT 0 +#define RDPTTY_NETLINK_MSG_MAXSIZE 12000 + +typedef struct _rdptty_data { + /* Per-device data */ + + /* The RDP device id for this */ + /* redirected serial port: */ + uint32_t device_id; + + /* The file handle of the AF_NETLINK device */ + /* for communicating with userspace: */ + int netlink_fh; + +} rdptty_data; + +enum rdptty_netlink_message_types { + RDPTTY_PING = 0x00, + RDPTTY_IOCTL = 0x01, + RDPTTY_SETMCTRL = 0x02, + RDPTTY_GETMCTRL = 0x03, + RDPTTY_GETSTATUS = 0x04, + RDPTTY_ADDPORT = 0x05, + RDPTTY_OPEN = 0x06, + RDPTTY_CLOSE = 0x07, + RDPTTY_READ = 0x08, + RDPTTY_WRITE = 0x09, + RDPTTY_DATA = 0x0A, + RDPTTY_START = 0x0B, + RDPTTY_STOP = 0x0C, + RDPTTY_GETBAUD = 0x0D, + RDPTTY_SETBAUD = 0x0E, + RDPTTY_TXEMPTY = 0x0F, + RDPTTY_TXFULL = 0x10, + RDPTTY_TXSTOP = 0x11, + RDPTTY_TXSTART = 0x12, + RDPTTY_RXEMPTY = 0x13, + RDPTTY_RXFULL = 0x14, + RDPTTY_RXSTOP = 0x15, + RDPTTY_RXSTART = 0x16, + RDPTTY_MSENABLE = 0x17, + RDPTTY_BREAKCTL = 0x18, + RDPTTY_SETTERMIOS = 0x19, + RDPTTY_GETTERMIOS = 0x1A, + RDPTTY_XCHAR = 0x1B, + RDPTTY_ASYNC = 0x40, + RDPTTY_REPLY = 0x80, +}; + +#define CMD_TO_STRING_ARRAY_DEF { \ + [0x00] = "RDPTTY_PING", \ + [0x01] = "RDPTTY_IOCTL", \ + [0x02] = "RDPTTY_SETMCTRL", \ + [0x03] = "RDPTTY_GETMCTRL", \ + [0x04] = "RDPTTY_GETSTATUS", \ + [0x05] = "RDPTTY_ADDPORT", \ + [0x06] = "RDPTTY_OPEN", \ + [0x07] = "RDPTTY_CLOSE", \ + [0x08] = "RDPTTY_READ", \ + [0x09] = "RDPTTY_WRITE", \ + [0x0A] = "RDPTTY_DATA", \ + [0x0B] = "RDPTTY_START", \ + [0x0C] = "RDPTTY_STOP", \ + [0x0D] = "RDPTTY_GETBAUD", \ + [0x0E] = "RDPTTY_SETBAUD", \ + [0x0F] = "RDPTTY_TXEMPTY", \ + [0x10] = "RDPTTY_TXFULL", \ + [0x11] = "RDPTTY_TXSTOP", \ + [0x12] = "RDPTTY_TXSTART", \ + [0x13] = "RDPTTY_RXEMPTY", \ + [0x14] = "RDPTTY_RXFULL", \ + [0x15] = "RDPTTY_RXSTOP", \ + [0x16] = "RDPTTY_RXSTART", \ + [0x17] = "RDPTTY_MSENABLE", \ + [0x18] = "RDPTTY_BREAKCTL", \ + [0x19] = "RDPTTY_SETTERMIOS", \ + [0x1A] = "RDPTTY_GETTERMIOS", \ + [0x1B] = "RDPTTY_XCHAR", \ + [0x40] = "RDPTTY_ASYNC", \ + [0x80] = "RDPTTY_REPLY", \ +} + +typedef struct rdptty_irq_data { + uint32_t device_id; + uint32_t mask; + uint8_t dtr; + uint8_t rts; + uint8_t cd; + uint8_t ri; + uint32_t mcr; + uint32_t msr; + uint32_t status; + uint32_t rx_len; + uint8_t rx_buf[0]; +} rdptty_irq_data_t; + +#ifndef __KERNEL__ + +typedef struct _rdptty_netlink_msg { + uint8_t type; + uint8_t reserved; + uint16_t len; + union { + uint8_t id[8]; + struct rdptty_mst { + uint32_t id; + uint32_t res; + } mst; + } id; + uint8_t data[0]; +} rdptty_netlink_msg; + + +typedef struct _rdptty_reg_num { +#if defined(__LITTLE_ENDIAN_BITFIELD) + uint64_t family:8; + uint64_t id:48; + uint64_t crc:8; +#elif defined(__BIG_ENDIAN_BITFIELD) + uint64_t crc:8; + uint64_t id:48; + uint64_t family:8; +#else +#error "Please fix " +#endif +} rdptty_reg_num; + +#endif + +#ifdef __KERNEL__ + +#include +#include +#include + +typedef struct _rdptty_reg_num { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u64 family:8, + id:48, + crc:8; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u64 crc:8, + id:48, + family:8; +#else +#error "Please fix " +#endif +} rdptty_reg_num; + + +/*** + *** Netlink/Connection ("cn") definitions + ***/ + +typedef struct rdptty_record { + struct tty_port * port; + struct rdptty_port * rdp_port; + struct module * owner; + unsigned char name[RDPTTY_MAXNAMELEN]; + unsigned long attempts; + int initialized; + u32 id; + int search_count; + atomic_t refcnt; + void * priv; + ssize_t priv_size; + long flags; + struct task_struct * thread; + struct semaphore mutex; + struct device_driver * driver; + struct device dev; + spinlock_t lock; + u32 seq; + struct rdptty_family * family; + void * family_data; + struct completion released; + struct list_head list; +} rdptty_record_t; + +typedef struct _rdptty_netlink_msg { + __u8 type; + __u8 reserved; + __u16 len; + union { + __u8 id[8]; + struct rdptty_mst { + __u32 id; + __u32 res; + } mst; + } id; + __u8 data[0]; +} rdptty_netlink_msg; + +typedef struct rdptty_port { + #define CMD_MAX 32 + #define CMD_OFFSET 4 + struct tty_port port; + struct list_head list; + struct rdptty_record rec; + spinlock_t cmd_lock; + unsigned char cmd_array[(CMD_MAX - CMD_OFFSET)]; + atomic_t already_opened; + uint32_t device_id; + unsigned char in_use; +} rdptty_port_t; + +int rdptty_netlink_send(struct rdptty_record *, rdptty_netlink_msg *, int); +int rdptty_init_netlink(void); +void rdptty_stop_netlink(void); + +#ifndef __RDPTTY_FAMILY_H +#define __RDPTTY_FAMILY_H + +#include +#include +#include + +#define MAXNAMELEN 32 + +struct rdptty_family_ops { + int (* ping)(struct rdptty_record *); + void (* pong)(struct rdptty_record *); +}; + +struct rdptty_family { + struct list_head family_entry; + u8 fid; + + struct rdptty_family_ops * fops; + + atomic_t refcnt; + u8 need_exit; +}; + +extern spinlock_t rdptty_flock; + +void rdptty_family_get(struct rdptty_family *); +void rdptty_family_put(struct rdptty_family *); +void __rdptty_family_get(struct rdptty_family *); +void __rdptty_family_put(struct rdptty_family *); +struct rdptty_family * rdptty_family_registered(u8); +void rdptty_unregister_family(struct rdptty_family *); +int rdptty_register_family(struct rdptty_family *); + +#endif /* __RDPTTY_FAMILY_H */ + + +typedef struct tty_operations rdptty_ops_t; + + +#endif /* __KERNEL__ */ + +#ifndef WIN32_SERIAL + +#define MAX_BAUD_RATE 460800 +#define MAX_BAUD_REMAINDER 4608 + +#define DIV_LATCH_LS 0x00 +#define XMT_HOLD_REGISTER 0x00 +#define XVR_BUFFER_REGISTER 0x00 +#define DIV_LATCH_MS 0x01 +#define FIFO_CONTROL_REGISTER 0x02 +#define LINE_CONTROL_REGISTER 0x03 +#define MODEM_CONTROL_REGISTER 0x04 +#define LINE_STATUS_REGISTER 0x05 +#define MODEM_STATUS_REGISTER 0x06 + +#define SERIAL_MCR_DTR 0x01 +#define SERIAL_MCR_RTS 0x02 +#define SERIAL_MCR_LOOP 0x10 + +#define SERIAL_MSR_CTS 0x10 +#define SERIAL_MSR_CD 0x80 +#define SERIAL_MSR_RI 0x40 +#define SERIAL_MSR_DSR 0x20 +#define SERIAL_MSR_MASK 0xf0 + +#define SERIAL_8_DATA 0x03 +#define SERIAL_7_DATA 0x02 +#define SERIAL_6_DATA 0x01 +#define SERIAL_5_DATA 0x00 + +#define SERIAL_ODD_PARITY 0X08 +#define SERIAL_EVEN_PARITY 0X18 +#define SERIAL_TWO_STOPB 0x04 +#define SERIAL_ONE_STOPB 0x00 + +#define DEFAULT_DIVISOR 0x30 /* gives 9600 baud rate */ +#define DEFAULT_LCR SERIAL_8_DATA /* 8, none , 1 */ + +#define SERIAL_LSR_OE 0x02 +#define SERIAL_LSR_PE 0x04 +#define SERIAL_LSR_FE 0x08 +#define SERIAL_LSR_BI 0x10 + +#define SERIAL_MSR_CTS 0x10 +#define SERIAL_MSR_CD 0x80 +#define SERIAL_MSR_RI 0x40 +#define SERIAL_MSR_DSR 0x20 +#define SERIAL_MSR_MASK 0xf0 + +#define LOOPMODE_BITS 0x41 /* LOOP1 = b6, LOOP0 = b0 (PORT B) */ +#define ALL_LOOPBACK 0x01 +#define MODEM_CTRL 0x40 +#define RS232_MODE 0x00 + +#endif + +#endif /* LINUX_RDPTTY_H */ diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/linux/include/linux/rdpuart.h posixrdp/posixxrdp.orig/linux/include/linux/rdpuart.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/linux/include/linux/rdpuart.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/linux/include/linux/rdpuart.h 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,371 @@ +/* + * + */ + +#ifndef LINUX_RDPUART_H +#define LINUX_RDPUART_H + +#include + +/* #define PORT_RDP PORT_UNKNOWN */ +/* #define PORT_RDP PORT_16550A */ +/* #define PORT_RDP PORT_8250 */ +#define PORT_RDP PORT_UARTLITE +#define PORT_RDPUART PORT_RDP +#define RDPUART_MAXNAMELEN 32 + +#define CN_IDX_RDPUART CN_IDX_CIFS + 0x10 +#define CN_VAL_RDPUART CN_VAL_CIFS + 0x10 +#define RDPUART_FAMILY_DEFAULT 0 +#define RDPUART_NETLINK_MSG_MAXSIZE 12000 + +typedef struct _rdpuart_data { + /* Per-device data */ + + /* The RDP device id for this */ + /* redirected serial port: */ + uint32_t device_id; + + /* The file handle of the AF_NETLINK device */ + /* for communicating with userspace: */ + int netlink_fh; + +} rdpuart_data; + +enum rdpuart_netlink_message_types { + RDPUART_PING = 0x00, + RDPUART_IOCTL = 0x01, + RDPUART_SETMCTRL = 0x02, + RDPUART_GETMCTRL = 0x03, + RDPUART_GETSTATUS = 0x04, + RDPUART_ADDPORT = 0x05, + RDPUART_OPEN = 0x06, + RDPUART_CLOSE = 0x07, + RDPUART_READ = 0x08, + RDPUART_WRITE = 0x09, + RDPUART_DATA = 0x0A, + RDPUART_START = 0x0B, + RDPUART_STOP = 0x0C, + RDPUART_GETBAUD = 0x0D, + RDPUART_SETBAUD = 0x0E, + RDPUART_TXEMPTY = 0x0F, + RDPUART_TXFULL = 0x10, + RDPUART_TXSTOP = 0x11, + RDPUART_TXSTART = 0x12, + RDPUART_RXEMPTY = 0x13, + RDPUART_RXFULL = 0x14, + RDPUART_RXSTOP = 0x15, + RDPUART_RXSTART = 0x16, + RDPUART_MSENABLE = 0x17, + RDPUART_BREAKCTL = 0x18, + RDPUART_SETTERMIOS = 0x19, + RDPUART_GETTERMIOS = 0x1A, + RDPUART_XCHAR = 0x1B, + RDPUART_ASYNC = 0x40, + RDPUART_REPLY = 0x80, +}; + +#define CMD_TO_STRING_ARRAY_DEF { \ + [0x00] = "RDPUART_PING", \ + [0x01] = "RDPUART_IOCTL", \ + [0x02] = "RDPUART_SETMCTRL", \ + [0x03] = "RDPUART_GETMCTRL", \ + [0x04] = "RDPUART_GETSTATUS", \ + [0x05] = "RDPUART_ADDPORT", \ + [0x06] = "RDPUART_OPEN", \ + [0x07] = "RDPUART_CLOSE", \ + [0x08] = "RDPUART_READ", \ + [0x09] = "RDPUART_WRITE", \ + [0x0A] = "RDPUART_DATA", \ + [0x0B] = "RDPUART_START", \ + [0x0C] = "RDPUART_STOP", \ + [0x0D] = "RDPUART_GETBAUD", \ + [0x0E] = "RDPUART_SETBAUD", \ + [0x0F] = "RDPUART_TXEMPTY", \ + [0x10] = "RDPUART_TXFULL", \ + [0x11] = "RDPUART_TXSTOP", \ + [0x12] = "RDPUART_TXSTART", \ + [0x13] = "RDPUART_RXEMPTY", \ + [0x14] = "RDPUART_RXFULL", \ + [0x15] = "RDPUART_RXSTOP", \ + [0x16] = "RDPUART_RXSTART", \ + [0x17] = "RDPUART_MSENABLE", \ + [0x18] = "RDPUART_BREAKCTL", \ + [0x19] = "RDPUART_SETTERMIOS", \ + [0x1A] = "RDPUART_GETTERMIOS", \ + [0x1B] = "RDPUART_XCHAR", \ + [0x40] = "RDPUART_ASYNC", \ + [0x80] = "RDPUART_REPLY", \ +} + +typedef struct rdpuart_irq_data { + uint32_t device_id; + uint32_t mask; + uint8_t dtr; + uint8_t rts; + uint8_t cd; + uint8_t ri; + uint32_t mcr; + uint32_t msr; + uint32_t status; + uint32_t rx_len; + uint8_t rx_buf[0]; +} rdpuart_irq_data_t; + +#ifndef __KERNEL__ + +typedef struct _rdpuart_netlink_msg { + uint8_t type; + uint8_t reserved; + uint16_t len; + union { + uint8_t id[8]; + struct rdpuart_mst { + uint32_t id; + uint32_t res; + } mst; + } id; + uint8_t data[0]; +} rdpuart_netlink_msg; + + +typedef struct _rdpuart_reg_num { +#if defined(__LITTLE_ENDIAN_BITFIELD) + uint64_t family:8; + uint64_t id:48; + uint64_t crc:8; +#elif defined(__BIG_ENDIAN_BITFIELD) + uint64_t crc:8; + uint64_t id:48; + uint64_t family:8; +#else +#error "Please fix " +#endif +} rdpuart_reg_num; + +#endif + +#ifdef __KERNEL__ + +#include +#include +#include + +typedef struct _rdpuart_reg_num { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u64 family:8, + id:48, + crc:8; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u64 crc:8, + id:48, + family:8; +#else +#error "Please fix " +#endif +} rdpuart_reg_num; + + +/*** + *** Netlink/Connection ("cn") definitions + ***/ + +typedef struct rdpuart_record { + struct uart_port * port; + struct rdpuart_port * rdp_port; + struct module * owner; + unsigned char name[RDPUART_MAXNAMELEN]; + unsigned long attempts; + int initialized; + u32 id; + int search_count; + atomic_t refcnt; + void * priv; + ssize_t priv_size; + long flags; + struct task_struct * thread; + struct semaphore mutex; + struct device_driver * driver; + struct device dev; + spinlock_t lock; + u32 seq; + struct rdpuart_family * family; + void * family_data; + struct completion released; + struct list_head list; +} rdpuart_record_t; + +typedef struct _rdpuart_netlink_msg { + __u8 type; + __u8 reserved; + __u16 len; + union { + __u8 id[8]; + struct rdpuart_mst { + __u32 id; + __u32 res; + } mst; + } id; + __u8 data[0]; +} rdpuart_netlink_msg; + +typedef struct rdpuart_port { + #define CMD_MAX 32 + #define CMD_OFFSET 4 + struct uart_port port; + struct timer_list timer; + struct list_head list; + struct rdpuart_record rec; + spinlock_t cmd_lock; + unsigned char cmd_array[(CMD_MAX - CMD_OFFSET)]; + atomic_t already_opened; + atomic_t poll_scheduled; + uint32_t device_id; +} rdpuart_port_t; + +int rdpuart_netlink_send(struct rdpuart_record *, rdpuart_netlink_msg *, int); +int rdpuart_init_netlink(void); +void rdpuart_stop_netlink(void); + +#ifndef __RDPUART_FAMILY_H +#define __RDPUART_FAMILY_H + +#include +#include +#include + +#define MAXNAMELEN 32 + +struct rdpuart_family_ops { + int (* ping)(struct rdpuart_record *); + void (* pong)(struct rdpuart_record *); +}; + +struct rdpuart_family { + struct list_head family_entry; + u8 fid; + + struct rdpuart_family_ops * fops; + + atomic_t refcnt; + u8 need_exit; +}; + +extern spinlock_t rdpuart_flock; + +void rdpuart_family_get(struct rdpuart_family *); +void rdpuart_family_put(struct rdpuart_family *); +void __rdpuart_family_get(struct rdpuart_family *); +void __rdpuart_family_put(struct rdpuart_family *); +struct rdpuart_family * rdpuart_family_registered(u8); +void rdpuart_unregister_family(struct rdpuart_family *); +int rdpuart_register_family(struct rdpuart_family *); + +#endif /* __RDPUART_FAMILY_H */ + + +typedef struct rdpuart_opset { + unsigned int (*tx_empty)(struct rdpuart_port *); + void (*set_mctrl)(struct rdpuart_port *, unsigned int mctrl); + unsigned int (*get_mctrl)(struct rdpuart_port *); + void (*stop_tx)(struct rdpuart_port *); + void (*start_tx)(struct rdpuart_port *); + void (*send_xchar)(struct rdpuart_port *, char ch); + void (*stop_rx)(struct rdpuart_port *); + void (*enable_ms)(struct rdpuart_port *); + void (*break_ctl)(struct rdpuart_port *, int ctl); + int (*startup)(struct rdpuart_port *); + void (*shutdown)(struct rdpuart_port *); + void (*flush_buffer)(struct rdpuart_port *); + void (*set_termios)(struct rdpuart_port *, struct ktermios *new, + struct ktermios *old); + void (*set_ldisc)(struct rdpuart_port *); + void (*pm)(struct rdpuart_port *, unsigned int state, + unsigned int oldstate); + int (*set_wake)(struct rdpuart_port *, unsigned int state); + + /* + * Return a string describing the type of the port + */ + const char *(*type)(struct rdpuart_port *); + + /* + * Release IO and memory resources used by the port. + * This includes iounmap if necessary. + */ + void (*release_port)(struct rdpuart_port *); + + /* + * Request IO and memory resources used by the port. + * This includes iomapping the port if necessary. + */ + int (*request_port)(struct rdpuart_port *); + void (*config_port)(struct rdpuart_port *, int); + int (*verify_port)(struct rdpuart_port *, struct serial_struct *); + int (*ioctl)(struct rdpuart_port *, unsigned int, unsigned long); +#ifdef CONFIG_CONSOLE_POLL + void (*poll_put_char)(struct rdpuart_port *, unsigned char); + int (*poll_get_char)(struct rdpuart_port *); +#endif +} rdpuart_ops_t; + + +#endif /* __KERNEL__ */ + +#ifndef WIN32_SERIAL + +#define MAX_BAUD_RATE 460800 +#define MAX_BAUD_REMAINDER 4608 + +#define DIV_LATCH_LS 0x00 +#define XMT_HOLD_REGISTER 0x00 +#define XVR_BUFFER_REGISTER 0x00 +#define DIV_LATCH_MS 0x01 +#define FIFO_CONTROL_REGISTER 0x02 +#define LINE_CONTROL_REGISTER 0x03 +#define MODEM_CONTROL_REGISTER 0x04 +#define LINE_STATUS_REGISTER 0x05 +#define MODEM_STATUS_REGISTER 0x06 + +#define SERIAL_MCR_DTR 0x01 +#define SERIAL_MCR_RTS 0x02 +#define SERIAL_MCR_LOOP 0x10 + +#define SERIAL_MSR_CTS 0x10 +#define SERIAL_MSR_CD 0x80 +#define SERIAL_MSR_RI 0x40 +#define SERIAL_MSR_DSR 0x20 +#define SERIAL_MSR_MASK 0xf0 + +#define SERIAL_8_DATA 0x03 +#define SERIAL_7_DATA 0x02 +#define SERIAL_6_DATA 0x01 +#define SERIAL_5_DATA 0x00 + +#define SERIAL_ODD_PARITY 0X08 +#define SERIAL_EVEN_PARITY 0X18 +#define SERIAL_TWO_STOPB 0x04 +#define SERIAL_ONE_STOPB 0x00 + +#define DEFAULT_DIVISOR 0x30 /* gives 9600 baud rate */ +#define DEFAULT_LCR SERIAL_8_DATA /* 8, none , 1 */ + +#define SERIAL_LSR_OE 0x02 +#define SERIAL_LSR_PE 0x04 +#define SERIAL_LSR_FE 0x08 +#define SERIAL_LSR_BI 0x10 + +#define SERIAL_MSR_CTS 0x10 +#define SERIAL_MSR_CD 0x80 +#define SERIAL_MSR_RI 0x40 +#define SERIAL_MSR_DSR 0x20 +#define SERIAL_MSR_MASK 0xf0 + +#define LOOPMODE_BITS 0x41 /* LOOP1 = b6, LOOP0 = b0 (PORT B) */ +#define ALL_LOOPBACK 0x01 +#define MODEM_CTRL 0x40 +#define RS232_MODE 0x00 + +#endif + +#endif /* LINUX_RDPUART_H */ diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/linux/reply.c posixrdp/posixxrdp.orig/linux/reply.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/linux/reply.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/linux/reply.c 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,307 @@ +/* + * reply.c + * + * Copyright (c) 2004+ Evgeniy Polyakov + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "common/os_calls.h" + +#define DEBUG +#ifndef NETLINK_CONNECTOR +#define NETLINK_CONNECTOR 11 +#endif + +/* Hopefully your userspace connector.h matches this kernel */ +/* #define CN_TEST_IDX CN_NETLINK_USERS + 3 */ +/* #define CN_TEST_VAL 0x456 */ +#define CN_TEST_IDX CN_IDX_RDPUART +#define CN_TEST_VAL CN_VAL_RDPUART + +#ifdef DEBUG +#define ulog(f, a...) fprintf(stdout, f, ##a) +#else +#define ulog(f, a...) do {} while (0) +#endif + + +static const char * cmdarray[] = CMD_TO_STRING_ARRAY_DEF; + +#define RDPUARTCMD(x) (cmdarray[(x & 0x0f)]) + + +static int need_exit; +static __u32 seq; + +static int netlink_send(int s, struct cn_msg * msg) { + struct nlmsghdr * nlh = (struct nlmsghdr *)NULL; + unsigned int size = 0; + int err = 0; + struct cn_msg * m = (struct cn_msg *)NULL; + rdpuart_netlink_msg * rmsg = (rdpuart_netlink_msg *)NULL; + char buf[128]; + + memset(buf, 0, sizeof(char) * 128); + size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len); + + nlh = (struct nlmsghdr *)buf; + nlh->nlmsg_seq = seq++; + nlh->nlmsg_pid = getpid(); + nlh->nlmsg_type = NLMSG_DONE; + nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh)); + nlh->nlmsg_flags = 0; + + m = NLMSG_DATA(nlh); +#if 0 + ulog("%s: [%08x.%08x] len=%u, seq=%u, ack=%u.\n", + __func__, msg->id.idx, msg->id.val, msg->len, msg->seq, msg->ack); +#endif + memcpy(m, msg, sizeof(*m) + msg->len); + + err = send(s, nlh, size, 0); + if (err == -1) + ulog("Failed to send: %s [%d].\n", + strerror(errno), errno); + + g_hexdump_file("/tmp/reply.hex", buf, size); + + return err; +} + +static void usage(void) { + printf( + "Usage: reply [options] [output file]\n" + "\n" + "\t-h\tthis help screen\n" + "\t-r\tsend reply packets in response to inbound packets received from the test module\n" + "\t-s\tsend buffers to the test module\n" + "\n" + "The default behavior of reply is to subscribe to the test module\n" + "and wait for state messages. Any ones received are dumped to the\n" + "specified output file (or stdout). The test module is assumed to\n" + "have an id of {%u.%u}\n" + "\n" + "If you get no output, then verify the cn_test module id matches\n" + "the expected id above.\n", CN_TEST_IDX, CN_TEST_VAL); +} + +int main(int argc, char *argv[]) { + int s = 0; + int res = 0; + int len = 0; + struct nlmsghdr * reply = (struct nlmsghdr *)NULL; + struct cn_msg * data = (struct cn_msg *)NULL; + FILE * out = (FILE *)NULL; + bool send_msgs = false; + bool send_rply = false; + struct sockaddr_nl l_local; + time_t tm; + struct pollfd pfd; + char buf[1024]; + + memset(&l_local, 0, sizeof(struct sockaddr_nl)); + memset(&tm, 0, sizeof(time_t)); + memset(&pfd, 0, sizeof(struct pollfd)); + memset(buf, 0, sizeof(char) * 1024); + + while ((s = getopt(argc, argv, "hrs")) != -1) { + switch (s) { + case 'r': + send_rply = true; + break; + + case 's': + send_msgs = true; + break; + + case 'h': + usage(); + res = 0; + return res; + + default: + /* getopt() outputs an error for us */ + usage(); + res = 1; + return res; + } + } + + if (argc != optind) { + out = fopen(argv[optind], "a+"); + if (!out) { + ulog("Unable to open %s for writing: %s\n", argv[1], strerror(errno)); + out = stdout; + } + } + else { + out = stdout; + } + + memset(buf, 0, sizeof(buf)); + + if ((s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR)) < 0) { + perror("socket"); + res = s; + return res; + } + + l_local.nl_family = AF_NETLINK; + l_local.nl_groups = -1; /* bitmask of requested groups */ + l_local.nl_pid = 0; + + ulog("subscribing to %u.%u\n", CN_TEST_IDX, CN_TEST_VAL); + + if ((res = bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl))) < 0) { + perror("bind"); + close(s); + return res; + } + +#if 0 + ulog(" >> 0 is defined <<\n"); + { + int on = 0x57; /* Additional group number */ + setsockopt(s, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &on, sizeof(on)); + } +#endif + if (send_msgs) { + int i = 0; + int j = 0; + + memset(buf, 0, sizeof(buf)); + data = (struct cn_msg *)buf; + data->id.idx = CN_TEST_IDX; + data->id.val = CN_TEST_VAL; + data->seq = seq++; + data->ack = 0; + data->len = sizeof(struct cn_msg) * 3; + + for (j = 0; j < 10; ++j) { + for (i = 0; i < 100; ++i) { + len = netlink_send(s, data); + } + ulog("%d messages have been sent to %08x.%08x.\n", i, data->id.idx, data->id.val); + } + return 0; + } + + pfd.fd = s; + + while (!need_exit) { + pfd.events = POLLIN; + pfd.revents = 0; + switch (poll(&pfd, 1, -1)) { + case 0: + need_exit = 1; + break; + case -1: + if (errno != EINTR) { + need_exit = 1; + break; + } + continue; + } + if (need_exit) { + break; + } + + memset(buf, 0, sizeof(buf)); + if ((len = recv(s, buf, sizeof(buf), 0)) < 0) { + perror("recv buf"); + close(s); + res = len; + return res; + } + reply = (struct nlmsghdr *)buf; + + switch (reply->nlmsg_type) { + case NLMSG_ERROR: + fprintf(out, "Error message received.\n"); + fflush(out); + break; + case NLMSG_DONE: + { + int seqid = 0; + int idx = 0; + int val = 0; + int ack = 0; + + data = (struct cn_msg *)NLMSG_DATA(reply); + rdpuart_netlink_msg * rdpmsg = (rdpuart_netlink_msg *)data->data; + + seqid = data->seq; + idx = data->id.idx; + val = data->id.val; + ack = data->ack; + + time(&tm); + fprintf(out, "%.24s : [%x.%x] [%08u.%08u] --> ", + ctime(&tm), data->id.idx, data->id.val, data->seq, data->ack); + fprintf(out, "\"%s\" \t (len = \"%d\")\n", RDPUARTCMD(rdpmsg->type), rdpmsg->type, rdpmsg->len); + fflush(out); + if (send_rply) { + unsigned char * tp = (unsigned char *)NULL; + unsigned char tbuf[1024]; + memset(tbuf, 0, sizeof(tbuf)); + data = (struct cn_msg *)tbuf; + data->id.idx = CN_TEST_IDX; + data->id.val = CN_TEST_VAL; + data->seq = seqid; + data->ack = 1; +// data->len = sizeof(struct cn_msg) * 1; + data->len = sizeof(rdpuart_netlink_msg) * 1; + tp = (unsigned char *)data->data; + memcpy(data->data, rdpmsg, sizeof(rdpuart_netlink_msg)); + len = netlink_send(s, data); + + ulog(" --> reply sent to %08x.%08x.\n", idx, val); + } + } + break; + default: + break; + } + } + + close(s); + return res; +} diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/linux/ucon.c posixrdp/posixxrdp.orig/linux/ucon.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/linux/ucon.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/linux/ucon.c 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,265 @@ +/* + * ucon.c + * + * Copyright (c) 2004+ Evgeniy Polyakov + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define DEBUG +#define NETLINK_CONNECTOR 11 + +/* Hopefully your userspace connector.h matches this kernel */ +/* #define CN_TEST_IDX CN_NETLINK_USERS + 3 */ +/* #define CN_TEST_VAL 0x456 */ +#define CN_TEST_IDX CN_IDX_RDPUART +#define CN_TEST_VAL CN_VAL_RDPUART + +#ifdef DEBUG +#define ulog(f, a...) fprintf(stdout, f, ##a) +#else +#define ulog(f, a...) do {} while (0) +#endif + + +static const char * cmdarray[] = CMD_TO_STRING_ARRAY_DEF; + +#define RDPUARTCMD(x) (cmdarray[(x & 0x0f)]) + + +static int need_exit; +static __u32 seq; + +static int netlink_send(int s, struct cn_msg *msg) { + struct nlmsghdr *nlh; + unsigned int size; + int err; + char buf[128]; + struct cn_msg *m; + rdpuart_netlink_msg * rmsg = (rdpuart_netlink_msg *)NULL; + + size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len); + + nlh = (struct nlmsghdr *)buf; + nlh->nlmsg_seq = seq++; + nlh->nlmsg_pid = getpid(); + nlh->nlmsg_type = NLMSG_DONE; + nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh)); + nlh->nlmsg_flags = 0; + + m = NLMSG_DATA(nlh); +#if 0 + ulog("%s: [%08x.%08x] len=%u, seq=%u, ack=%u.\n", + __func__, msg->id.idx, msg->id.val, msg->len, msg->seq, msg->ack); +#endif + memcpy(m, msg, sizeof(*m) + msg->len); + + err = send(s, nlh, size, 0); + if (err == -1) + ulog("Failed to send: %s [%d].\n", + strerror(errno), errno); + + return err; +} + +static void usage(void) +{ + printf( + "Usage: ucon [options] [output file]\n" + "\n" + "\t-h\tthis help screen\n" + "\t-s\tsend buffers to the test module\n" + "\n" + "The default behavior of ucon is to subscribe to the test module\n" + "and wait for state messages. Any ones received are dumped to the\n" + "specified output file (or stdout). The test module is assumed to\n" + "have an id of {%u.%u}\n" + "\n" + "If you get no output, then verify the cn_test module id matches\n" + "the expected id above.\n", CN_TEST_IDX, CN_TEST_VAL); +} + +int main(int argc, char *argv[]) { + int s = 0; + int res = 0; + int len = 0; + struct nlmsghdr * reply = (struct nlmsghdr *)NULL; + struct cn_msg * data = (struct cn_msg *)NULL; + FILE * out = (FILE *)NULL; + bool send_msgs = false; + struct sockaddr_nl l_local; + time_t tm; + struct pollfd pfd; + char buf[1024]; + + while ((s = getopt(argc, argv, "hs")) != -1) { + switch (s) { + case 's': + send_msgs = true; + break; + + case 'h': + usage(); + res = 0; + return res; + + default: + /* getopt() outputs an error for us */ + usage(); + res = 1; + return res; + } + } + + if (argc != optind) { + out = fopen(argv[optind], "a+"); + if (!out) { + ulog("Unable to open %s for writing: %s\n", + argv[1], strerror(errno)); + out = stdout; + } + } else { + out = stdout; + } + + memset(buf, 0, sizeof(buf)); + + if ((s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR)) < 0) { + perror("socket"); + res = s; + return res; + } + + l_local.nl_family = AF_NETLINK; + l_local.nl_groups = -1; /* bitmask of requested groups */ + l_local.nl_pid = 0; + + ulog("subscribing to %u.%u\n", CN_TEST_IDX, CN_TEST_VAL); + + if ((res = bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl))) < 0) { + perror("bind"); + close(s); + return res; + } + +#if 0 + { + int on = 0x57; /* Additional group number */ + setsockopt(s, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &on, sizeof(on)); + } +#endif + if (send_msgs) { + int i = 0; + int j = 0; + + memset(buf, 0, sizeof(buf)); + + data = (struct cn_msg *)buf; + + data->id.idx = CN_TEST_IDX; + data->id.val = CN_TEST_VAL; + data->seq = seq++; + data->ack = 0; + data->len = sizeof(struct cn_msg) * 3; + + for (j=0; j<10; ++j) { + for (i=0; i<100; ++i) { + len = netlink_send(s, data); + } + ulog("%d messages have been sent to %08x.%08x.\n", i, data->id.idx, data->id.val); + } + return 0; + } + + + pfd.fd = s; + + while (!need_exit) { + pfd.events = POLLIN; + pfd.revents = 0; + switch (poll(&pfd, 1, -1)) { + case 0: + need_exit = 1; + break; + case -1: + if (errno != EINTR) { + need_exit = 1; + break; + } + continue; + } + if (need_exit) { + break; + } + + memset(buf, 0, sizeof(buf)); + if ((len = recv(s, buf, sizeof(buf), 0)) < 0) { + perror("recv buf"); + close(s); + res = len; + return res; + } + reply = (struct nlmsghdr *)buf; + + switch (reply->nlmsg_type) { + case NLMSG_ERROR: + fprintf(out, "Error message received.\n"); + fflush(out); + break; + case NLMSG_DONE: + { + data = (struct cn_msg *)NLMSG_DATA(reply); + rdpuart_netlink_msg * rdpmsg = (rdpuart_netlink_msg *)data->data; + + time(&tm); + fprintf(out, "%.24s : [%x.%x] [%08u.%08u] --> ", + ctime(&tm), data->id.idx, data->id.val, data->seq, data->ack); + fprintf(out, "\"%s\" \t (len = \"%d\")\n", RDPUARTCMD(rdpmsg->type), rdpmsg->type, rdpmsg->len); + fflush(out); + } + break; + default: + break; + } + } + + close(s); + return res; +} diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/mc/Makefile.am posixrdp/posixxrdp.orig/mc/Makefile.am --- xrdp/xrdp-0.5.0~20100303cvs.orig/mc/Makefile.am 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/mc/Makefile.am 2010-11-08 09:56:45.000000000 +0100 @@ -1,9 +1,17 @@ AM_CFLAGS = \ + -pthread \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ -DXRDP_SBIN_PATH=\"${sbindir}\" \ -DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \ - -DXRDP_PID_PATH=\"${localstatedir}/run\" + -DXRDP_PID_PATH=\"${localstatedir}/run\" \ + -D_FILE_OFFSET_BITS=64 \ + -D_REENTRANT \ + -D_GNU_SOURCE \ + -D_XOPEN_SOURCE_EXTENDED + +AM_LDFLAGS = \ + -lpthread INCLUDES = \ -I$(top_srcdir)/common @@ -14,4 +22,4 @@ libmc_la_SOURCES = mc.c libmc_la_LIBADD = \ - $(top_srcdir)/common/libcommon.la + $(top_builddir)/common/libcommon.la diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/project.log posixrdp/posixxrdp.orig/project.log --- xrdp/xrdp-0.5.0~20100303cvs.orig/project.log 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/project.log 2010-11-08 09:56:43.000000000 +0100 @@ -0,0 +1,24 @@ +2009-10-30 14:33:49 INFO: Bootstrapping "project" in "/usr/src/xrdp/trunk" +2009-10-30 14:33:49 DEBUG: cvs not found as new-style vcs, trying as monolithic +2009-10-30 14:33:49 DEBUG: bzr not found as new-style vcs, trying as monolithic +2009-10-30 14:33:49 INFO: Initializing new repository in '/usr/src/xrdp/trunk'... +2009-10-30 14:33:49 INFO: $ cvs -f -d /usr/src/xrdp/cvs rlog -r:HEAD -b xrdp 2>&1 +2009-10-30 14:33:49 DEBUG: Executing cvs -f -d /usr/src/xrdp/cvs rlog -r:HEAD -b xrdp ('/usr/src/xrdp') +2009-10-30 14:33:49 INFO: [Ok] +2009-10-30 14:33:49 INFO: Cached information about 0 pending changesets +2009-10-30 14:33:49 CRITICAL: Checkout of project failed! +2009-10-30 14:33:49 CRITICAL: Something unexpected! +Traceback (most recent call last): + File "/usr/lib/pymodules/python2.5/vcpx/tailor.py", line 153, in __call__ + self.bootstrap() + File "/usr/lib/pymodules/python2.5/vcpx/tailor.py", line 80, in bootstrap + actual = dwd.checkoutUpstreamRevision(revision) + File "/usr/lib/pymodules/python2.5/vcpx/source.py", line 242, in checkoutUpstreamRevision + last = self._checkoutUpstreamRevision(revision) + File "/usr/lib/pymodules/python2.5/vcpx/repository/cvs.py", line 681, in _checkoutUpstreamRevision + last = CvspsWorkingDir._checkoutUpstreamRevision(self, revision) + File "/usr/lib/pymodules/python2.5/vcpx/repository/cvsps.py", line 446, in _checkoutUpstreamRevision + initialcset = csets.next() + File "/usr/lib/pymodules/python2.5/vcpx/statefile.py", line 108, in next + raise StopIteration +StopIteration diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/rdp/Makefile.am posixrdp/posixxrdp.orig/rdp/Makefile.am --- xrdp/xrdp-0.5.0~20100303cvs.orig/rdp/Makefile.am 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/rdp/Makefile.am 2010-11-08 09:56:45.000000000 +0100 @@ -1,9 +1,17 @@ AM_CFLAGS = \ + -pthread \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ -DXRDP_SBIN_PATH=\"${sbindir}\" \ -DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \ - -DXRDP_PID_PATH=\"${localstatedir}/run\" + -DXRDP_PID_PATH=\"${localstatedir}/run\" \ + -D_FILE_OFFSET_BITS=64 \ + -D_REENTRANT \ + -D_GNU_SOURCE \ + -D_XOPEN_SOURCE_EXTENDED + +AM_LDFLAGS = \ + -lpthread INCLUDES = \ -I$(top_srcdir)/common @@ -23,4 +31,4 @@ rdp_tcp.c librdp_la_LIBADD = \ - $(top_srcdir)/common/libcommon.la + $(top_builddir)/common/libcommon.la diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/rdp/rdp_orders.c posixrdp/posixxrdp.orig/rdp/rdp_orders.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/rdp/rdp_orders.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/rdp/rdp_orders.c 2010-11-08 09:56:45.000000000 +0100 @@ -22,11 +22,15 @@ #include "rdp.h" +#ifndef NULL +#define NULL 0 +#endif + /*****************************************************************************/ struct rdp_orders* APP_CC rdp_orders_create(struct rdp_rdp* owner) { - struct rdp_orders* self; + struct rdp_orders* self = (struct rdp_orders *)NULL; self = (struct rdp_orders*)g_malloc(sizeof(struct rdp_orders), 1); self->rdp_layer = owner; @@ -37,8 +41,8 @@ void APP_CC rdp_orders_delete(struct rdp_orders* self) { - int i; - int j; + int i = 0; + int j = 0; if (self == 0) { @@ -77,8 +81,8 @@ rdp_orders_in_present(struct stream* s, int* present, int flags, int size) { - int bits; - int i; + int bits = 0; + int i = 0; if (flags & RDP_ORDER_SMALL) { @@ -108,7 +112,7 @@ static void APP_CC rdp_orders_in_coord(struct stream* s, int* coord, int delta) { - int change; + int change = 0; if (delta) { @@ -126,7 +130,7 @@ static void APP_CC rdp_orders_parse_bounds(struct rdp_orders* self, struct stream* s) { - int present; + int present = 0; in_uint8(s, present); if (present & 1) @@ -169,10 +173,10 @@ rdp_orders_process_colcache(struct rdp_orders* self, struct stream* s, int flags) { - struct rdp_colormap* colormap; - struct stream* rec_s; - int cache_id; - int i; + struct rdp_colormap* colormap = (struct rdp_colormap *)NULL; + struct stream* rec_s = (struct stream *)NULL; + int cache_id = 0; + int i = 0; colormap = (struct rdp_colormap*)g_malloc(sizeof(struct rdp_colormap), 1); in_uint8(s, cache_id); @@ -206,26 +210,26 @@ rdp_orders_process_raw_bmpcache(struct rdp_orders* self, struct stream* s, int flags) { - int cache_idx; - int bufsize; - int cache_id; - int width; - int height; - int bpp; - int Bpp; - int x; - int y; - char* inverted; - char* dst; - struct rdp_bitmap* bitmap; - struct stream* rec_s; + int cache_idx = 0; + int bufsize = 0; + int cache_id = 0; + int width = 0; + int height = 0; + int bpp = 0; + int Bpp = 0; + int x = 0; + int y = 0; + char* inverted = (char *)NULL; + char* dst = (char *)NULL; + struct rdp_bitmap* bitmap = (struct rdp_bitmap *)NULL; + struct stream* rec_s = (struct stream *)NULL; in_uint8(s, cache_id); in_uint8s(s, 1); in_uint8(s, width); in_uint8(s, height); in_uint8(s, bpp); - Bpp = (bpp + 7) / 8; + Bpp = (bpp == 32) ? 3 : (bpp + 7) / 8; in_uint16_le(s, bufsize); in_uint16_le(s, cache_idx); inverted = (char*)g_malloc(width * height * Bpp, 0); @@ -255,11 +259,18 @@ in_uint8(s, dst[x * 3 + 2]); } } + else if (Bpp == 4) + { + for (x = 0; x < width; x++) + { + in_uint32_le(s, ((tui32*)dst)[x]); + } + } } bitmap = (struct rdp_bitmap*)g_malloc(sizeof(struct rdp_bitmap), 0); bitmap->width = width; bitmap->height = height; - bitmap->bpp = bpp; + bitmap->bpp = (bpp == 32) ? 24 : bpp; bitmap->data = inverted; if (self->cache_bitmap[cache_id][cache_idx] != 0) { @@ -292,29 +303,29 @@ rdp_orders_process_bmpcache(struct rdp_orders* self, struct stream* s, int flags) { - char* data; - char* bmpdata; - int cache_idx; - int size; - int cache_id; - int width; - int height; - int bpp; - int Bpp; - int bufsize; - int pad1; - int pad2; - int row_size; - int final_size; - struct rdp_bitmap* bitmap; - struct stream* rec_s; + char* data = (char *)NULL; + char* bmpdata = (char *)NULL; + int cache_idx = 0; + int size = 0; + int cache_id = 0; + int width = 0; + int height = 0; + int bpp = 0; + int Bpp = 0; + int bufsize = 0; + int pad1 = 0; + int pad2 = 0; + int row_size = 0; + int final_size = 0; + struct rdp_bitmap* bitmap = (struct rdp_bitmap *)NULL; + struct stream* rec_s = (struct stream *)NULL; in_uint8(s, cache_id); in_uint8(s, pad1); in_uint8(s, width); in_uint8(s, height); in_uint8(s, bpp); - Bpp = (bpp + 7) / 8; + Bpp = (bpp == 32) ? 3 : (bpp + 7) / 8; in_uint16_le(s, bufsize); in_uint16_le(s, cache_idx); if (flags & 1024) @@ -340,7 +351,7 @@ bitmap = (struct rdp_bitmap*)g_malloc(sizeof(struct rdp_bitmap), 0); bitmap->width = width; bitmap->height = height; - bitmap->bpp = bpp; + bitmap->bpp = (bpp == 32) ? 24 : bpp; bitmap->data = bmpdata; if (self->cache_bitmap[cache_id][cache_idx] != 0) { @@ -373,17 +384,17 @@ rdp_orders_process_fontcache(struct rdp_orders* self, struct stream* s, int flags) { - struct stream* rec_s; - int font; - int nglyphs; - int character; - int offset; - int baseline; - int width; - int height; - int i; - int datasize; - char* data; + struct stream* rec_s = (struct stream *)NULL; + int font = 0; + int nglyphs = 0; + int character = 0; + int offset = 0; + int baseline = 0; + int width = 0; + int height = 0; + int i = 0; + int datasize = 0; + char* data = (char *)NULL; in_uint8(s, font); in_uint8(s, nglyphs); @@ -425,10 +436,10 @@ static int APP_CC rdp_orders_process_secondary_order(struct rdp_orders* self, struct stream* s) { - short length; - int flags; - int type; - char* next_order; + short length = 0; + int flags = 0; + int type = 0; + char* next_order = (char *)NULL; in_uint16_le(s, length); in_uint16_le(s, flags); @@ -461,7 +472,7 @@ static void APP_CC rdp_orders_in_color(struct stream* s, int* color) { - int i; + int i = 0; in_uint8(s, i); *color = i; @@ -523,9 +534,9 @@ rdp_orders_process_text2(struct rdp_orders* self, struct stream* s, int present, int delta) { - int fgcolor; - int bgcolor; - struct stream* rec_s; + int fgcolor = 0; + int bgcolor = 0; + struct stream* rec_s = (struct stream *)NULL; if (present & 0x000001) { @@ -662,7 +673,7 @@ rdp_orders_process_destblt(struct rdp_orders* self, struct stream* s, int present, int delta) { - struct stream* rec_s; + struct stream* rec_s = (struct stream *)NULL; if (present & 0x01) { @@ -715,9 +726,9 @@ rdp_orders_process_patblt(struct rdp_orders* self, struct stream* s, int present, int delta) { - int fgcolor; - int bgcolor; - struct stream* rec_s; + int fgcolor = 0; + int bgcolor = 0; + struct stream* rec_s = (struct stream *)NULL; if (present & 0x0001) { @@ -867,9 +878,9 @@ rdp_orders_process_line(struct rdp_orders* self, struct stream* s, int present, int delta) { - int bgcolor; - int fgcolor; - struct stream* rec_s; + int bgcolor = 0; + int fgcolor = 0; + struct stream* rec_s = (struct stream *)NULL; if (present & 0x0001) { @@ -949,9 +960,9 @@ rdp_orders_process_rect(struct rdp_orders* self, struct stream* s, int present, int delta) { - int i; - int fgcolor; - struct stream* rec_s; + int i = 0; + int fgcolor = 0; + struct stream* rec_s = (struct stream *)NULL; if (present & 0x01) { @@ -1017,8 +1028,8 @@ rdp_orders_process_desksave(struct rdp_orders* self, struct stream* s, int present, int delta) { - int width; - int height; + int width = 0; + int height = 0; if (present & 0x01) { @@ -1044,8 +1055,8 @@ { in_uint8(s, self->state.desksave_action); } -// width = (self->state.desksave_right - self->state.desksave_left) + 1; -// height = (self->state.desksave_bottom - self->state.desksave_top) + 1; + width = (self->state.desksave_right - self->state.desksave_left) + 1; + height = (self->state.desksave_bottom - self->state.desksave_top) + 1; if (self->state.desksave_action == 0) { // ui_desktop_save(os->offset, os->left, os->top, width, height); @@ -1062,9 +1073,9 @@ rdp_orders_process_memblt(struct rdp_orders* self, struct stream* s, int present, int delta) { - struct rdp_bitmap* bitmap; - struct stream* rec_s; - char* bmpdata; + struct rdp_bitmap* bitmap = (struct rdp_bitmap *)NULL; + struct stream* rec_s = (struct stream *)NULL; + char* bmpdata = (char *)NULL; if (present & 0x0001) { @@ -1200,11 +1211,11 @@ rdp_orders_process_orders(struct rdp_orders* self, struct stream* s, int num_orders) { - int processed; - int order_flags; - int size; - int present; - int delta; + int processed = 0; + int order_flags = 0; + int size = 0; + int present = 0; + int delta = 0; processed = 0; while (processed < num_orders) @@ -1304,19 +1315,19 @@ /* returns pointer, it might return bmpdata if the data dosen't need to be converted, else it mallocs it. The calling function must free it if needed */ -char* APP_CC +char * APP_CC rdp_orders_convert_bitmap(int in_bpp, int out_bpp, char* bmpdata, int width, int height, int* palette) { - char* out; - char* src; - char* dst; - int i; - int j; - int red; - int green; - int blue; - int pixel; + char* out = (char *)NULL; + char* src = (char *)NULL; + char* dst = (char *)NULL; + int i = 0; + int j = 0; + int red = 0; + int green = 0; + int blue = 0; + int pixel = 0; if ((in_bpp == 8) && (out_bpp == 8)) { @@ -1338,6 +1349,26 @@ } return out; } + if ((in_bpp == 8) && (out_bpp == 15)) + { + out = (char*)g_malloc(width * height * 2, 0); + src = bmpdata; + dst = out; + for (i = 0; i < height; i++) + { + for (j = 0; j < width; j++) + { + pixel = *((tui8*)src); + pixel = palette[pixel]; + SPLITCOLOR32(red, green, blue, pixel); + pixel = COLOR15(red, green, blue); + *((tui16*)dst) = pixel; + src++; + dst += 2; + } + } + return out; + } if ((in_bpp == 8) && (out_bpp == 16)) { out = (char*)g_malloc(width * height * 2, 0); @@ -1372,12 +1403,16 @@ SPLITCOLOR32(red, green, blue, pixel); pixel = COLOR24RGB(red, green, blue); *((tui32*)dst) = pixel; - src++;; + src++; dst += 4; } } return out; } + if ((in_bpp == 15) && (out_bpp == 15)) + { + return bmpdata; + } if ((in_bpp == 15) && (out_bpp == 16)) { out = (char*)g_malloc(width * height * 2, 0); @@ -1469,10 +1504,10 @@ int APP_CC rdp_orders_convert_color(int in_bpp, int out_bpp, int in_color, int* palette) { - int pixel; - int red; - int green; - int blue; + int pixel = 0; + int red = 0; + int green = 0; + int blue = 0; if ((in_bpp == 8) && (out_bpp == 8)) { @@ -1481,6 +1516,13 @@ pixel = COLOR8(red, green, blue); return pixel; } + if ((in_bpp == 8) && (out_bpp == 15)) + { + pixel = palette[in_color]; + SPLITCOLOR32(red, green, blue, pixel); + pixel = COLOR15(red, green, blue); + return pixel; + } if ((in_bpp == 8) && (out_bpp == 16)) { pixel = palette[in_color]; @@ -1495,6 +1537,17 @@ pixel = COLOR24BGR(red, green, blue); return pixel; } + if ((in_bpp == 8) && (out_bpp == 32)) + { + pixel = palette[in_color]; + SPLITCOLOR32(red, green, blue, pixel); + pixel = COLOR32BGR(red, green, blue); + return pixel; + } + if ((in_bpp == 15) && (out_bpp == 15)) + { + return in_color; + } if ((in_bpp == 15) && (out_bpp == 16)) { pixel = in_color; @@ -1509,6 +1562,13 @@ pixel = COLOR24BGR(red, green, blue); return pixel; } + if ((in_bpp == 15) && (out_bpp == 32)) + { + pixel = in_color; + SPLITCOLOR15(red, green, blue, pixel); + pixel = COLOR32BGR(red, green, blue); + return pixel; + } if ((in_bpp == 16) && (out_bpp == 16)) { return in_color; @@ -1520,9 +1580,27 @@ pixel = COLOR24BGR(red, green, blue); return pixel; } + if ((in_bpp == 16) && (out_bpp == 32)) + { + pixel = in_color; + SPLITCOLOR16(red, green, blue, pixel); + pixel = COLOR24BGR(red, green, blue); + return pixel; + } if ((in_bpp == 24) && (out_bpp == 24)) { return in_color; } + if ((in_bpp == 24) && (out_bpp == 32)) + { + pixel = in_color; + SPLITCOLOR32(red, green, blue, pixel); + pixel = COLOR32BGR(red, green, blue); + return pixel; + } + if ((in_bpp == 32) && (out_bpp == 32)) + { + return in_color; + } return 0; } diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/rdp/rdp_rdp.c posixrdp/posixxrdp.orig/rdp/rdp_rdp.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/rdp/rdp_rdp.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/rdp/rdp_rdp.c 2010-11-08 09:56:45.000000000 +0100 @@ -22,6 +22,10 @@ #include "rdp.h" +#ifndef NULL +#define NULL 0 +#endif + /*****************************************************************************/ struct rdp_rdp* APP_CC rdp_rdp_create(struct mod* owner) @@ -222,11 +226,11 @@ static int APP_CC rdp_rdp_out_bmpcache_caps(struct rdp_rdp* self, struct stream* s) { - int Bpp; + int Bpp = 0; out_uint16_le(s, RDP_CAPSET_BMPCACHE); out_uint16_le(s, RDP_CAPLEN_BMPCACHE); - Bpp = (self->mod->rdp_bpp + 7) / 8; + Bpp = (self->mod->rdp_bpp == 32) ? 3 : (self->mod->rdp_bpp + 7) / 8; out_uint8s(s, 24); /* unused */ out_uint16_le(s, 0x258); /* entries */ out_uint16_le(s, 0x100 * Bpp); /* max cell size */ @@ -508,26 +512,26 @@ static void APP_CC rdp_rdp_process_bitmap_updates(struct rdp_rdp* self, struct stream* s) { - int num_updates; - int left; - int top; - int right; - int bottom; - int width; - int height; - int cx; - int cy; - int bpp; - int Bpp; - int compress; - int bufsize; - int size; - int i; - int x; - int y; - char* data; - char* bmpdata0; - char* bmpdata1; + int num_updates = 0; + int left = 0; + int top = 0; + int right = 0; + int bottom = 0; + int width = 0; + int height = 0; + int cx = 0; + int cy = 0; + int bpp = 0; + int Bpp = 0; + int compress = 0; + int bufsize = 0; + int size = 0; + int i = 0; + int x = 0; + int y = 0; + char* data = NULL; + char* bmpdata0 = NULL; + char* bmpdata1 = NULL; in_uint16_le(s, num_updates); for (i = 0; i < num_updates; i++) @@ -539,7 +543,7 @@ in_uint16_le(s, width); in_uint16_le(s, height); in_uint16_le(s, bpp); - Bpp = (bpp + 7) / 8; + Bpp = (bpp == 32) ? 3 : (bpp + 7) / 8; in_uint16_le(s, compress); in_uint16_le(s, bufsize); cx = (right - left) + 1; @@ -869,6 +873,7 @@ { int data_pdu_type; int ctype; + int clen; int len; int rv; @@ -877,7 +882,8 @@ in_uint16_le(s, len); in_uint8(s, data_pdu_type); in_uint8(s, ctype); - in_uint8s(s, 2); /* clen */ + in_uint16_le(s, clen); + clen -= 18; switch (data_pdu_type) { case RDP_DATA_PDU_UPDATE: @@ -915,9 +921,9 @@ static void APP_CC rdp_rdp_process_bitmap_caps(struct rdp_rdp* self, struct stream* s) { - int width; - int height; - int bpp; + int width = 0; + int height = 0; + int bpp = 0; in_uint16_le(s, bpp); in_uint8s(s, 6); @@ -933,12 +939,12 @@ static int APP_CC rdp_rdp_process_server_caps(struct rdp_rdp* self, struct stream* s, int len) { - int n; - int ncapsets; - int capset_type; - int capset_length; - char* next; - char* start; + int n = 0; + int ncapsets = 0; + int capset_type = 0; + int capset_length = 0; + char* next = NULL; + char* start = NULL; start = s->p; in_uint16_le(s, ncapsets); @@ -1035,9 +1041,9 @@ int APP_CC rdp_rdp_process_demand_active(struct rdp_rdp* self, struct stream* s) { - int type; - int len_src_descriptor; - int len_combined_caps; + int type = 0; + int len_src_descriptor = 0; + int len_combined_caps = 0; in_uint32_le(s, self->share_id); in_uint16_le(s, len_src_descriptor); @@ -1064,9 +1070,11 @@ rdp_rec_check_file(struct rdp_rdp* self) { char file_name[256]; - int index; - int len; - struct stream* s; + int index = 0; + int len = 0; + struct stream* s = (struct stream *)NULL; + + g_memset(file_name,0,sizeof(char) * 256); if (self->rec_fd == 0) { @@ -1098,8 +1106,8 @@ int APP_CC rdp_rec_write_item(struct rdp_rdp* self, struct stream* s) { - int len; - int time; + int len = 0; + int time = 0; if (self->rec_fd == 0) { diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/alsa.c posixrdp/posixxrdp.orig/sesman/chansrv/alsa.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/alsa.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/alsa.c 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,283 @@ +#include "alsa.h" +#include "dbg.h" + +alsa * g_alsa = (alsa *)NULL; + +static int APP_CC g_alsa_setup_fifo(struct _alsa *, const char *); + +/*****************************************************/ +int APP_CC +g_alsa_init(void) { + int rv = 0; + void * g_alsa_handle = (void *)NULL; + g_alsa_handle = dlopen("libasound.so.2", RTLD_LAZY | RTLD_GLOBAL); + if (g_alsa_handle == NULL) { + rv = -1; + } + else { + /* instantiate the alsa class: */ + g_alsa = (alsa *)g_malloc(sizeof(alsa),1); + g_alsa->hLocal = g_alsa_handle; + g_alsa->hALSA = dlopen(0, RTLD_LAZY); + + g_alsa->fifo = -1; + + /* associate class methods with their corresponding libasound2 functions: */ + g_alsa->snd_pcm_file_open = dlsym(g_alsa->hALSA,"snd_pcm_file_open"); + g_alsa->snd_pcm_dmix_open = dlsym(g_alsa->hALSA,"snd_pcm_dmix_open"); + g_alsa->snd_pcm_null_open = dlsym(g_alsa->hALSA,"snd_pcm_null_open"); + g_alsa->snd_pcm_set_params = dlsym(g_alsa->hALSA,"snd_pcm_set_params"); + g_alsa->snd_pcm_open = dlsym(g_alsa->hALSA,"snd_pcm_open"); + g_alsa->snd_pcm_open_lconf = dlsym(g_alsa->hALSA,"snd_pcm_open_lconf"); + g_alsa->snd_pcm_close = dlsym(g_alsa->hALSA,"snd_pcm_close"); + g_alsa->snd_pcm_name = dlsym(g_alsa->hALSA,"snd_pcm_name"); + g_alsa->snd_pcm_type = dlsym(g_alsa->hALSA,"snd_pcm_type"); + g_alsa->snd_pcm_stream = dlsym(g_alsa->hALSA,"snd_pcm_stream"); + g_alsa->snd_pcm_poll_descriptors_count = dlsym(g_alsa->hALSA,"snd_pcm_poll_descriptors_count"); + g_alsa->snd_pcm_poll_descriptors = dlsym(g_alsa->hALSA,"snd_pcm_poll_descriptors"); + g_alsa->snd_pcm_poll_descriptors_revents = dlsym(g_alsa->hALSA,"snd_pcm_poll_descriptors_revents"); + g_alsa->snd_pcm_nonblock = dlsym(g_alsa->hALSA,"snd_pcm_nonblock"); + g_alsa->snd_pcm_access_mask_none = dlsym(g_alsa->hALSA,"snd_pcm_access_mask_none"); + g_alsa->snd_pcm_access_mask_any = dlsym(g_alsa->hALSA,"snd_pcm_access_mask_any"); + g_alsa->snd_pcm_access_mask_empty = dlsym(g_alsa->hALSA,"snd_pcm_access_mask_empty"); + g_alsa->snd_pcm_access_mask_set = dlsym(g_alsa->hALSA,"snd_pcm_access_mask_set"); + g_alsa->snd_pcm_access_mask_reset = dlsym(g_alsa->hALSA,"snd_pcm_access_mask_reset"); + g_alsa->snd_pcm_format_mask_none = dlsym(g_alsa->hALSA,"snd_pcm_format_mask_none"); + g_alsa->snd_pcm_format_mask_any = dlsym(g_alsa->hALSA,"snd_pcm_format_mask_any"); + g_alsa->snd_pcm_format_mask_empty = dlsym(g_alsa->hALSA,"snd_pcm_format_mask_empty"); + g_alsa->snd_pcm_format_mask_set = dlsym(g_alsa->hALSA,"snd_pcm_format_mask_set"); + g_alsa->snd_pcm_format_mask_reset = dlsym(g_alsa->hALSA,"snd_pcm_format_mask_reset"); + g_alsa->snd_pcm_format_mask_malloc = dlsym(g_alsa->hALSA,"snd_pcm_format_mask_malloc"); + g_alsa->snd_pcm_format_mask_free = dlsym(g_alsa->hALSA,"snd_pcm_format_mask_free"); + g_alsa->snd_pcm_format_mask_copy = dlsym(g_alsa->hALSA,"snd_pcm_format_mask_copy"); + g_alsa->snd_pcm_state = dlsym(g_alsa->hALSA,"snd_pcm_state"); + g_alsa->snd_pcm_prepare = dlsym(g_alsa->hALSA,"snd_pcm_prepare"); + g_alsa->snd_pcm_reset = dlsym(g_alsa->hALSA,"snd_pcm_reset"); + g_alsa->snd_pcm_start = dlsym(g_alsa->hALSA,"snd_pcm_start"); + g_alsa->snd_pcm_drop = dlsym(g_alsa->hALSA,"snd_pcm_drop"); + g_alsa->snd_pcm_drain = dlsym(g_alsa->hALSA,"snd_pcm_drain"); + g_alsa->snd_pcm_pause = dlsym(g_alsa->hALSA,"snd_pcm_pause"); + g_alsa->snd_pcm_resume = dlsym(g_alsa->hALSA,"snd_pcm_resume"); + g_alsa->snd_pcm_delay = dlsym(g_alsa->hALSA,"snd_pcm_delay"); + g_alsa->snd_pcm_writei = dlsym(g_alsa->hALSA,"snd_pcm_writei"); + g_alsa->snd_pcm_writen = dlsym(g_alsa->hALSA,"snd_pcm_writen"); + g_alsa->snd_pcm_readi = dlsym(g_alsa->hALSA,"snd_pcm_readi"); + g_alsa->snd_pcm_readn = dlsym(g_alsa->hALSA,"snd_pcm_readn"); + g_alsa->snd_pcm_link = dlsym(g_alsa->hALSA,"snd_pcm_link"); + g_alsa->snd_pcm_unlink = dlsym(g_alsa->hALSA,"snd_pcm_unlink"); + g_alsa->snd_pcm_wait = dlsym(g_alsa->hALSA,"snd_pcm_wait"); + g_alsa->snd_pcm_avail_update = dlsym(g_alsa->hALSA,"snd_pcm_avail_update"); + g_alsa->snd_pcm_avail = dlsym(g_alsa->hALSA,"snd_pcm_avail"); + g_alsa->snd_pcm_bytes_to_samples = dlsym(g_alsa->hALSA,"snd_pcm_bytes_to_samples"); + g_alsa->snd_pcm_samples_to_bytes = dlsym(g_alsa->hALSA,"snd_pcm_samples_to_bytes"); + g_alsa->snd_async_add_pcm_handler = dlsym(g_alsa->hALSA,"snd_async_add_pcm_handler"); + g_alsa->snd_async_handler_get_pcm = dlsym(g_alsa->hALSA,"snd_async_handler_get_pcm"); + g_alsa->snd_pcm_hw_params_can_pause = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_can_pause"); + g_alsa->snd_pcm_hw_params_can_resume = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_can_resume"); + g_alsa->snd_pcm_info = dlsym(g_alsa->hALSA,"snd_pcm_info"); + g_alsa->snd_pcm_hw_params_current = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_current"); + g_alsa->snd_pcm_info_sizeof = dlsym(g_alsa->hALSA,"snd_pcm_info_sizeof"); + g_alsa->snd_pcm_info_malloc = dlsym(g_alsa->hALSA,"snd_pcm_info_malloc"); + g_alsa->snd_pcm_info_free = dlsym(g_alsa->hALSA,"snd_pcm_info_free"); + g_alsa->snd_pcm_info_copy = dlsym(g_alsa->hALSA,"snd_pcm_info_copy"); + g_alsa->snd_pcm_info_get_device = dlsym(g_alsa->hALSA,"snd_pcm_info_get_device"); + g_alsa->snd_pcm_info_get_subdevice = dlsym(g_alsa->hALSA,"snd_pcm_info_get_subdevice"); + g_alsa->snd_pcm_info_get_stream = dlsym(g_alsa->hALSA,"snd_pcm_info_get_stream"); + g_alsa->snd_pcm_info_get_card = dlsym(g_alsa->hALSA,"snd_pcm_info_get_card"); + g_alsa->snd_pcm_info_get_id = dlsym(g_alsa->hALSA,"snd_pcm_info_get_id"); + g_alsa->snd_pcm_info_get_name = dlsym(g_alsa->hALSA,"snd_pcm_info_get_name"); + g_alsa->snd_pcm_info_get_subdevice_name = dlsym(g_alsa->hALSA,"snd_pcm_info_get_subdevice_name"); + g_alsa->snd_pcm_info_get_class = dlsym(g_alsa->hALSA,"snd_pcm_info_get_class"); + g_alsa->snd_pcm_info_get_subclass = dlsym(g_alsa->hALSA,"snd_pcm_info_get_subclass"); + g_alsa->snd_pcm_info_get_subdevices_count = dlsym(g_alsa->hALSA,"snd_pcm_info_get_subdevices_count"); + g_alsa->snd_pcm_info_get_subdevices_avail = dlsym(g_alsa->hALSA,"snd_pcm_info_get_subdevices_avail"); + g_alsa->snd_pcm_info_get_sync = dlsym(g_alsa->hALSA,"snd_pcm_info_get_sync"); + g_alsa->snd_pcm_info_set_device = dlsym(g_alsa->hALSA,"snd_pcm_info_set_device"); + g_alsa->snd_pcm_info_set_subdevice = dlsym(g_alsa->hALSA,"snd_pcm_info_set_subdevice"); + g_alsa->snd_pcm_info_set_stream = dlsym(g_alsa->hALSA,"snd_pcm_info_set_stream"); + g_alsa->snd_pcm_type_name = dlsym(g_alsa->hALSA,"snd_pcm_type_name"); + g_alsa->snd_pcm_stream_name = dlsym(g_alsa->hALSA,"snd_pcm_stream_name"); + g_alsa->snd_pcm_access_name = dlsym(g_alsa->hALSA,"snd_pcm_access_name"); + g_alsa->snd_pcm_format_name = dlsym(g_alsa->hALSA,"snd_pcm_format_name"); + g_alsa->snd_pcm_format_description = dlsym(g_alsa->hALSA,"snd_pcm_format_description"); + g_alsa->snd_pcm_subformat_name = dlsym(g_alsa->hALSA,"snd_pcm_subformat_name"); + g_alsa->snd_pcm_subformat_description = dlsym(g_alsa->hALSA,"snd_pcm_subformat_description"); + g_alsa->snd_pcm_format_value = dlsym(g_alsa->hALSA,"snd_pcm_format_value"); + g_alsa->snd_pcm_tstamp_mode_name = dlsym(g_alsa->hALSA,"snd_pcm_tstamp_mode_name"); + g_alsa->snd_pcm_state_name = dlsym(g_alsa->hALSA,"snd_pcm_state_name"); + g_alsa->snd_pcm_dump = dlsym(g_alsa->hALSA,"snd_pcm_dump"); + g_alsa->snd_pcm_dump_hw_setup = dlsym(g_alsa->hALSA,"snd_pcm_dump_hw_setup"); + g_alsa->snd_pcm_dump_sw_setup = dlsym(g_alsa->hALSA,"snd_pcm_dump_sw_setup"); + g_alsa->snd_pcm_dump_setup = dlsym(g_alsa->hALSA,"snd_pcm_dump_setup"); + g_alsa->snd_pcm_hw_params_dump = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_dump"); + g_alsa->snd_pcm_sw_params_dump = dlsym(g_alsa->hALSA,"snd_pcm_sw_params_dump"); + g_alsa->snd_pcm_status_dump = dlsym(g_alsa->hALSA,"snd_pcm_status_dump"); + g_alsa->snd_pcm_hw_params_any = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_any"); + g_alsa->snd_pcm_hw_params_get_sbits = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_get_sbits"); + g_alsa->snd_pcm_hw_params_sizeof = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_sizeof"); + g_alsa->snd_pcm_hw_params_malloc = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_malloc"); + g_alsa->snd_pcm_hw_params_free = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_free"); + g_alsa->snd_pcm_hw_params_copy = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_copy"); + g_alsa->snd_pcm_hw_params_set_access = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_set_access"); + g_alsa->snd_pcm_hw_params_get_access = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_get_access"); + g_alsa->snd_pcm_hw_params_set_access_mask = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_set_access_mask"); + g_alsa->snd_pcm_hw_params_get_access_mask = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_get_access_mask"); + g_alsa->snd_pcm_hw_params_get_format = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_get_format"); + g_alsa->snd_pcm_hw_params_set_format = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_set_format"); + g_alsa->snd_pcm_hw_params_set_format_mask = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_set_format_mask"); + g_alsa->snd_pcm_hw_params_get_format_mask = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_get_format_mask"); + g_alsa->snd_pcm_hw_params_get_subformat = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_get_subformat"); + g_alsa->snd_pcm_hw_params_set_subformat = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_set_subformat"); + g_alsa->snd_pcm_hw_params_set_subformat_mask = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_set_subformat_mask"); + g_alsa->snd_pcm_hw_params_get_subformat_mask = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_get_subformat_mask"); + g_alsa->snd_pcm_hw_params_get_rate = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_get_rate"); + g_alsa->snd_pcm_hw_params_set_rate = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_set_rate"); + g_alsa->snd_pcm_hw_params_get_rate_min = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_get_rate_min"); + g_alsa->snd_pcm_hw_params_get_rate_max = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_get_rate_max"); + g_alsa->snd_pcm_hw_params_set_rate_min = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_set_rate_min"); + g_alsa->snd_pcm_hw_params_set_rate_max = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_set_rate_max"); + g_alsa->snd_pcm_hw_params_set_rate_minmax = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_set_rate_minmax"); + g_alsa->snd_pcm_hw_params_set_rate_near = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_set_rate_near"); + g_alsa->snd_pcm_hw_params_set_rate_resample = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_set_rate_resample"); + g_alsa->snd_pcm_hw_params_get_rate_resample = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_get_rate_resample"); + g_alsa->snd_pcm_hw_params_get_channels = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_get_channels"); + g_alsa->snd_pcm_hw_params_set_channels = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_set_channels"); + g_alsa->snd_pcm_hw_params_get_min_align = dlsym(g_alsa->hALSA,"snd_pcm_hw_params_get_min_align"); + g_alsa->snd_config_make_compound = dlsym(g_alsa->hALSA,"snd_config_make_compound"); + g_alsa->snd_config_make = dlsym(g_alsa->hALSA,"snd_config_make"); + g_alsa->snd_config_make_string = dlsym(g_alsa->hALSA,"snd_config_make_string"); + g_alsa->snd_config_make_integer = dlsym(g_alsa->hALSA,"snd_config_make_integer"); + g_alsa->snd_config_make_integer64 = dlsym(g_alsa->hALSA,"snd_config_make_integer64"); + g_alsa->snd_config_make_real = dlsym(g_alsa->hALSA,"snd_config_make_real"); + g_alsa->snd_config_make_pointer = dlsym(g_alsa->hALSA,"snd_config_make_pointer"); + g_alsa->snd_config_imake_string = dlsym(g_alsa->hALSA,"snd_config_imake_string"); + g_alsa->snd_config_imake_integer = dlsym(g_alsa->hALSA,"snd_config_imake_integer"); + g_alsa->snd_config_imake_integer64 = dlsym(g_alsa->hALSA,"snd_config_imake_integer64"); + g_alsa->snd_config_imake_real = dlsym(g_alsa->hALSA,"snd_config_imake_real"); + g_alsa->snd_config_imake_pointer = dlsym(g_alsa->hALSA,"snd_config_imake_pointer"); + g_alsa->snd_config_load = dlsym(g_alsa->hALSA,"snd_config_load"); + g_alsa->snd_config_top = dlsym(g_alsa->hALSA,"snd_config_top"); + g_alsa->snd_config_load_override = dlsym(g_alsa->hALSA,"snd_config_load_override"); + g_alsa->snd_config_save = dlsym(g_alsa->hALSA,"snd_config_save"); + g_alsa->snd_config_update = dlsym(g_alsa->hALSA,"snd_config_update"); + g_alsa->snd_config_search = dlsym(g_alsa->hALSA,"snd_config_search"); + g_alsa->snd_config_searchv = dlsym(g_alsa->hALSA,"snd_config_searchv"); + g_alsa->snd_config_search_definition = dlsym(g_alsa->hALSA,"snd_config_search_definition"); + g_alsa->snd_config_expand = dlsym(g_alsa->hALSA,"snd_config_expand"); + g_alsa->snd_config_add = dlsym(g_alsa->hALSA,"snd_config_add"); + g_alsa->snd_config_delete = dlsym(g_alsa->hALSA,"snd_config_delete"); + g_alsa->snd_config_delete_compound_members = dlsym(g_alsa->hALSA,"snd_config_delete_compound_members"); + g_alsa->snd_config_copy = dlsym(g_alsa->hALSA,"snd_config_copy"); + g_alsa->snd_config_get_type = dlsym(g_alsa->hALSA,"snd_config_get_type"); + g_alsa->snd_config_set_id = dlsym(g_alsa->hALSA,"snd_config_set_id"); + g_alsa->snd_config_set_integer = dlsym(g_alsa->hALSA,"snd_config_set_integer"); + g_alsa->snd_config_set_integer64 = dlsym(g_alsa->hALSA,"snd_config_set_integer64"); + g_alsa->snd_config_set_real = dlsym(g_alsa->hALSA,"snd_config_set_real"); + g_alsa->snd_config_set_string = dlsym(g_alsa->hALSA,"snd_config_set_string"); + g_alsa->snd_config_set_ascii = dlsym(g_alsa->hALSA,"snd_config_set_ascii"); + g_alsa->snd_config_set_pointer = dlsym(g_alsa->hALSA,"snd_config_set_pointer"); + g_alsa->snd_config_get_id = dlsym(g_alsa->hALSA,"snd_config_get_id"); + g_alsa->snd_config_get_integer = dlsym(g_alsa->hALSA,"snd_config_get_integer"); + g_alsa->snd_config_get_integer64 = dlsym(g_alsa->hALSA,"snd_config_get_integer64"); + g_alsa->snd_config_get_real = dlsym(g_alsa->hALSA,"snd_config_get_real"); + g_alsa->snd_config_get_ireal = dlsym(g_alsa->hALSA,"snd_config_get_ireal"); + g_alsa->snd_config_get_string = dlsym(g_alsa->hALSA,"snd_config_get_string"); + g_alsa->snd_config_get_ascii = dlsym(g_alsa->hALSA,"snd_config_get_ascii"); + g_alsa->snd_config_get_pointer = dlsym(g_alsa->hALSA,"snd_config_get_pointer"); + g_alsa->snd_config_iterator_first = dlsym(g_alsa->hALSA,"snd_config_iterator_first"); + g_alsa->snd_config_iterator_next = dlsym(g_alsa->hALSA,"snd_config_iterator_next"); + g_alsa->snd_config_iterator_end = dlsym(g_alsa->hALSA,"snd_config_iterator_end"); + g_alsa->snd_config_iterator_entry = dlsym(g_alsa->hALSA,"snd_config_iterator_entry"); + g_alsa->snd_config_test_id = dlsym(g_alsa->hALSA,"snd_config_test_id"); + g_alsa->snd_names_list = dlsym(g_alsa->hALSA,"snd_names_list"); + g_alsa->snd_config_get_bool_ascii = dlsym(g_alsa->hALSA,"snd_config_get_bool_ascii"); + g_alsa->snd_config_get_bool = dlsym(g_alsa->hALSA,"snd_config_get_bool"); + g_alsa->snd_config_get_ctl_iface_ascii = dlsym(g_alsa->hALSA,"snd_config_get_ctl_iface_ascii"); + g_alsa->snd_config_get_ctl_iface = dlsym(g_alsa->hALSA,"snd_config_get_ctl_iface"); + g_alsa->snd_config = dlsym(g_alsa->hALSA,"snd_config"); + g_alsa->setup_fifo = &g_alsa_setup_fifo; + } + return rv; +} + + +/*****************************************************/ +int APP_CC +g_alsa_deinit(void) { + int rv = 0; + if (g_alsa != NULL) { + if (g_alsa->pcm != NULL) { + g_alsa->snd_pcm_close(g_alsa->pcm); + g_alsa->pcm = NULL; + } + if (g_alsa->fifo != -1) { + close(g_alsa->fifo); + g_alsa->fifo = -1; + } + dlclose(g_alsa->hLocal); + dlclose(g_alsa->hALSA); + g_memset(g_alsa,0,sizeof(alsa)); + //g_free(g_alsa); + g_alsa = (alsa *)NULL; + } + return rv; +} + + +/*****************************************************/ +static int APP_CC +g_alsa_setup_fifo(struct _alsa * self, const char * fpath) { + int rv = 0; + snd_config_t * top_pcm_cfg = (snd_config_t *)NULL; + snd_config_t * null_cfg = (snd_config_t *)NULL; + snd_config_t * pcm_cfg = (snd_config_t *)NULL; + snd_config_t * slave_cfg = (snd_config_t *)NULL; + snd_config_t * tmp = (snd_config_t *)NULL; + + MDBGLOG("sound","g_alsa_setup_fifo: fpath = %s\0",fpath); + + if (fpath != NULL && g_strlen(fpath) > 0) { + rv = mkfifo(fpath, 0644); + rv = 0; + } + + if (rv > -1 && 1==2) { + self->snd_config_search(self->snd_config,"pcm",&top_pcm_cfg); + self->snd_config_make_compound(&pcm_cfg,"xrdp",0); + self->snd_config_imake_string(&tmp,"type","file"); + self->snd_config_add(pcm_cfg,tmp); + self->snd_config_imake_string(&tmp,"file",AUDIO_FIFO_PATH); + self->snd_config_add(pcm_cfg,tmp); + self->snd_config_make_compound(&null_cfg,"pcm",0); + self->snd_config_imake_string(&tmp,"type","null"); + self->snd_config_add(null_cfg,tmp); + self->snd_config_make_compound(&slave_cfg,"slave",0); + self->snd_config_add(slave_cfg,null_cfg); + self->snd_config_add(pcm_cfg,slave_cfg); + //self->snd_config_add(top_pcm_cfg,pcm_cfg); + //self->snd_config_add(self->snd_config,pcm_cfg); + //DBGLOG("sound","hereE"); + //self->snd_config_imake_string(&tmp,"main_playback","xrdp"); + //DBGLOG("sound","hereF"); + //self->snd_config_add(top_pcm_cfg,tmp); + MDBGLOG("sound","hereG: self->snd_config = %d",(int)self->snd_config); + } + + if (1==2) { + if (rv > -1) { + rv = self->snd_pcm_null_open(&(self->pcm_null),"xrdp_null",SND_PCM_STREAM_PLAYBACK,1); + if (rv > -1) { + rv = self->snd_pcm_file_open(&(self->pcm),"xrdp",fpath,-1,NULL,-1,0,"raw",0644,self->pcm_null,1); + } + } + } + + if (rv < 0) { + close(self->fifo); + unlink(fpath); + } + + MDBGLOG("sound","g_alsa_setup_fifo: done (rv = %d)\0",rv); + + return rv; +} diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/alsa.h posixrdp/posixxrdp.orig/sesman/chansrv/alsa.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/alsa.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/alsa.h 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,262 @@ +#ifndef _XRDP_ALSA_ +#define _XRDP_ALSA_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "defines.h" +#include "arch.h" +#include "os_calls.h" + +struct snd_pcm_direct_open_conf; +struct slave_params; +typedef struct snd_pcm_direct_open_conf snd_pcm_direct_open_conf_t; +typedef struct slave_params slave_params_t; + +/* */ +/* pseudo-class: "alsa" */ +typedef struct _alsa { + /* members: */ + void * hALSA; + void * hLocal; + char * device; /* playback device */ + snd_pcm_format_t format; /* = SND_PCM_FORMAT_S16 */ + unsigned int rate; + unsigned int channels; + unsigned int buffer_time; + int resample; + snd_pcm_sframes_t buffer_size; + snd_output_t * output; + int fifo; + snd_pcm_t * pcm; + snd_pcm_t * pcm_null; + + /* mapped members: */ + snd_config_t * snd_config; + + /* mapped methods: */ + int (*snd_pcm_file_open)(snd_pcm_t **, const char *, const char *, int, const char *, int, int, const char *, int, snd_pcm_t *, int); + int (*snd_pcm_dmix_open)(snd_pcm_t **, const char *, snd_pcm_direct_open_conf_t *, slave_params_t *, snd_config_t *, snd_config_t *, snd_pcm_stream_t, int); + int (*snd_pcm_null_open)(snd_pcm_t **, const char *, snd_pcm_stream_t, int); + int (*snd_pcm_set_params)(snd_pcm_t *, snd_pcm_format_t, snd_pcm_access_t, unsigned int, unsigned int, int, unsigned int); + int (*snd_pcm_open)(snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode); + int (*snd_pcm_open_lconf)(snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode, snd_config_t *lconf); + int (*snd_pcm_close)(snd_pcm_t *pcm); + const char * (*snd_pcm_name)(snd_pcm_t *pcm); + snd_pcm_type_t (*snd_pcm_type)(snd_pcm_t *pcm); + snd_pcm_stream_t (*snd_pcm_stream)(snd_pcm_t *pcm); + int (*snd_pcm_poll_descriptors_count)(snd_pcm_t *pcm); + int (*snd_pcm_poll_descriptors)(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space); + int (*snd_pcm_poll_descriptors_revents)(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents); + int (*snd_pcm_nonblock)(snd_pcm_t *pcm, int nonblock); + int (*snd_pcm_info)(snd_pcm_t *pcm, snd_pcm_info_t *info); + int (*snd_pcm_hw_params_current)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); + long (*snd_pcm_bytes_to_samples)(snd_pcm_t *pcm, ssize_t bytes); + ssize_t (*snd_pcm_samples_to_bytes)(snd_pcm_t *pcm, long samples); + int (*snd_async_add_pcm_handler)(snd_async_handler_t **handler, snd_pcm_t *pcm, snd_async_callback_t callback, void *private_data); + snd_pcm_t * (*snd_async_handler_get_pcm)(snd_async_handler_t *handler); + int (*snd_pcm_hw_params_can_pause)(const snd_pcm_hw_params_t *params); + int (*snd_pcm_hw_params_can_resume)(const snd_pcm_hw_params_t *params); + snd_pcm_state_t (*snd_pcm_state)(snd_pcm_t *pcm); + int (*snd_pcm_prepare)(snd_pcm_t *pcm); + int (*snd_pcm_reset)(snd_pcm_t *pcm); + int (*snd_pcm_start)(snd_pcm_t *pcm); + int (*snd_pcm_drop)(snd_pcm_t *pcm); + int (*snd_pcm_drain)(snd_pcm_t *pcm); + int (*snd_pcm_pause)(snd_pcm_t *pcm, int enable); + int (*snd_pcm_resume)(snd_pcm_t *pcm); + int (*snd_pcm_delay)(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp); + snd_pcm_sframes_t (*snd_pcm_writei)(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size); + snd_pcm_sframes_t (*snd_pcm_writen)(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size); + snd_pcm_sframes_t (*snd_pcm_readi)(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size); + snd_pcm_sframes_t (*snd_pcm_readn)(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size); + int (*snd_pcm_link)(snd_pcm_t *pcm1, snd_pcm_t *pcm2); + int (*snd_pcm_unlink)(snd_pcm_t *pcm); + int (*snd_pcm_wait)(snd_pcm_t *pcm, int timeout); + snd_pcm_sframes_t (*snd_pcm_avail_update)(snd_pcm_t *pcm); + snd_pcm_sframes_t (*snd_pcm_avail)(snd_pcm_t *pcm); + + + /* streams */ + size_t (*snd_pcm_info_sizeof)(void); + int (*snd_pcm_info_malloc)(snd_pcm_info_t **ptr); + void (*snd_pcm_info_free)(snd_pcm_info_t *obj); + void (*snd_pcm_info_copy)(snd_pcm_info_t *dst, const snd_pcm_info_t *src); + unsigned int (*snd_pcm_info_get_device)(const snd_pcm_info_t *obj); + unsigned int (*snd_pcm_info_get_subdevice)(const snd_pcm_info_t *obj); + snd_pcm_stream_t (*snd_pcm_info_get_stream)(const snd_pcm_info_t *obj); + int (*snd_pcm_info_get_card)(const snd_pcm_info_t *obj); + const char * (*snd_pcm_info_get_id)(const snd_pcm_info_t *obj); + const char * (*snd_pcm_info_get_name)(const snd_pcm_info_t *obj); + const char * (*snd_pcm_info_get_subdevice_name)(const snd_pcm_info_t *obj); + snd_pcm_class_t (*snd_pcm_info_get_class)(const snd_pcm_info_t *obj); + snd_pcm_subclass_t (*snd_pcm_info_get_subclass)(const snd_pcm_info_t *obj); + unsigned int (*snd_pcm_info_get_subdevices_count)(const snd_pcm_info_t *obj); + unsigned int (*snd_pcm_info_get_subdevices_avail)(const snd_pcm_info_t *obj); + snd_pcm_sync_id_t (*snd_pcm_info_get_sync)(const snd_pcm_info_t *obj); + void (*snd_pcm_info_set_device)(snd_pcm_info_t *obj, unsigned int val); + void (*snd_pcm_info_set_subdevice)(snd_pcm_info_t *obj, unsigned int val); + void (*snd_pcm_info_set_stream)(snd_pcm_info_t *obj, snd_pcm_stream_t val); + + /* descriptions */ + const char * (*snd_pcm_type_name)(snd_pcm_type_t type); + const char * (*snd_pcm_stream_name)(const snd_pcm_stream_t stream); + const char * (*snd_pcm_access_name)(const snd_pcm_access_t _access); + const char * (*snd_pcm_format_name)(const snd_pcm_format_t format); + const char * (*snd_pcm_format_description)(const snd_pcm_format_t format); + const char * (*snd_pcm_subformat_name)(const snd_pcm_subformat_t subformat); + const char * (*snd_pcm_subformat_description)(const snd_pcm_subformat_t subformat); + snd_pcm_format_t (*snd_pcm_format_value)(const char *name); + const char * (*snd_pcm_tstamp_mode_name)(const snd_pcm_tstamp_t mode); + const char * (*snd_pcm_state_name)(const snd_pcm_state_t state); + + /* debug */ + int (*snd_pcm_dump)(snd_pcm_t *pcm, snd_output_t *out); + int (*snd_pcm_dump_hw_setup)(snd_pcm_t *pcm, snd_output_t *out); + int (*snd_pcm_dump_sw_setup)(snd_pcm_t *pcm, snd_output_t *out); + int (*snd_pcm_dump_setup)(snd_pcm_t *pcm, snd_output_t *out); + int (*snd_pcm_hw_params_dump)(snd_pcm_hw_params_t *params, snd_output_t *out); + int (*snd_pcm_sw_params_dump)(snd_pcm_sw_params_t *params, snd_output_t *out); + int (*snd_pcm_status_dump)(snd_pcm_status_t *status, snd_output_t *out); + + /* hardware */ + int (*snd_pcm_hw_params_any)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); + int (*snd_pcm_hw_params_get_sbits)(const snd_pcm_hw_params_t *params); + size_t (*snd_pcm_hw_params_sizeof)(void); + int (*snd_pcm_hw_params_malloc)(snd_pcm_hw_params_t **ptr); + void (*snd_pcm_hw_params_free)(snd_pcm_hw_params_t *obj); + void (*snd_pcm_hw_params_copy)(snd_pcm_hw_params_t *dst, const snd_pcm_hw_params_t *src); + int (*snd_pcm_hw_params_set_access)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t _access); + int (*snd_pcm_hw_params_get_access)(const snd_pcm_hw_params_t *params, snd_pcm_access_t *_access); + int (*snd_pcm_hw_params_set_access_mask)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_mask_t *mask); + int (*snd_pcm_hw_params_get_access_mask)(snd_pcm_hw_params_t *params, snd_pcm_access_mask_t *mask); + void (*snd_pcm_access_mask_none)(snd_pcm_access_mask_t *mask); + void (*snd_pcm_access_mask_any)(snd_pcm_access_mask_t *mask); + int (*snd_pcm_access_mask_empty)(const snd_pcm_access_mask_t *mask); + void (*snd_pcm_access_mask_set)(snd_pcm_access_mask_t *mask, snd_pcm_access_t val); + void (*snd_pcm_access_mask_reset)(snd_pcm_access_mask_t *mask, snd_pcm_access_t val); + void (*snd_pcm_format_mask_none)(snd_pcm_format_mask_t *mask); + void (*snd_pcm_format_mask_any)(snd_pcm_format_mask_t *mask); + int (*snd_pcm_format_mask_empty)(const snd_pcm_format_mask_t *mask); + void (*snd_pcm_format_mask_set)(snd_pcm_format_mask_t *mask, snd_pcm_format_t val); + void (*snd_pcm_format_mask_reset)(snd_pcm_format_mask_t *mask, snd_pcm_format_t val); + int (*snd_pcm_format_mask_malloc)(snd_pcm_format_mask_t **ptr); + void (*snd_pcm_format_mask_free)(snd_pcm_format_mask_t *obj); + void (*snd_pcm_format_mask_copy)(snd_pcm_format_mask_t *dst, const snd_pcm_format_mask_t *src); + int (*snd_pcm_hw_params_get_format)(const snd_pcm_hw_params_t *params, snd_pcm_format_t *val); + int (*snd_pcm_hw_params_set_format)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t val); + int (*snd_pcm_hw_params_set_format_mask)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_mask_t *mask); + void (*snd_pcm_hw_params_get_format_mask)(snd_pcm_hw_params_t *params, snd_pcm_format_mask_t *mask); + int (*snd_pcm_hw_params_get_subformat)(const snd_pcm_hw_params_t *params, snd_pcm_subformat_t *subformat); + int (*snd_pcm_hw_params_set_subformat)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_subformat_t subformat); + int (*snd_pcm_hw_params_set_subformat_mask)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_subformat_mask_t *mask); + void (*snd_pcm_hw_params_get_subformat_mask)(snd_pcm_hw_params_t *params, snd_pcm_subformat_mask_t *mask); + int (*snd_pcm_hw_params_get_rate)(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir); + int (*snd_pcm_hw_params_get_rate_min)(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir); + int (*snd_pcm_hw_params_get_rate_max)(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir); + int (*snd_pcm_hw_params_set_rate)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int dir); + int (*snd_pcm_hw_params_set_rate_min)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir); + int (*snd_pcm_hw_params_set_rate_max)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir); + int (*snd_pcm_hw_params_set_rate_minmax)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *min, int *mindir, unsigned int *max, int *maxdir); + int (*snd_pcm_hw_params_set_rate_near)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir); + int (*snd_pcm_hw_params_set_rate_resample)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val); + int (*snd_pcm_hw_params_get_rate_resample)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val); + int (*snd_pcm_hw_params_get_channels)(const snd_pcm_hw_params_t *params, unsigned int *val); + int (*snd_pcm_hw_params_set_channels)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val); + int (*snd_pcm_hw_params_get_min_align)(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val); + + /* external PCM plugins */ + int (*snd_pcm_parse_control_id)(snd_config_t *conf, snd_ctl_elem_id_t *ctl_id, int *cardp, int *cchannelsp, int *hwctlp); + + /* configuration */ + int (*snd_config_make_compound)(snd_config_t **, const char *, int); + int (*snd_config_make)(snd_config_t **, const char *, snd_config_type_t); + int (*snd_config_make_string)(snd_config_t **config, const char *key); + int (*snd_config_make_integer)(snd_config_t **config, const char *key); + int (*snd_config_make_integer64)(snd_config_t **config, const char *key); + int (*snd_config_make_real)(snd_config_t **config, const char *key); + int (*snd_config_make_pointer)(snd_config_t **config, const char *key); + int (*snd_config_imake_string)(snd_config_t **config, const char *key, const char *ascii); + int (*snd_config_imake_integer)(snd_config_t **config, const char *key, const long value); + int (*snd_config_imake_integer64)(snd_config_t **config, const char *key, const long long value); + int (*snd_config_imake_real)(snd_config_t **config, const char *key, const double value); + int (*snd_config_imake_pointer)(snd_config_t **config, const char *key, const void *ptr); + int (*snd_config_load)(snd_config_t *, snd_input_t *); + int (*snd_config_top)(snd_config_t **); + int (*snd_config_load_override)(snd_config_t *config, snd_input_t *in); + int (*snd_config_save)(snd_config_t *config, snd_output_t *out); + int (*snd_config_update)(void); + int (*snd_config_search)(snd_config_t *config, const char *key, snd_config_t **result); + int (*snd_config_searchv)(snd_config_t *config, snd_config_t **result,...); + int (*snd_config_search_definition)(snd_config_t *config, const char *base, const char *key, snd_config_t **result); + int (*snd_config_expand)(snd_config_t *config, snd_config_t *root, const char *args, snd_config_t *private_data, snd_config_t **result); + int (*snd_config_evaluate)(snd_config_t *config, snd_config_t *root, snd_config_t *private_data, snd_config_t **result); + int (*snd_config_add)(snd_config_t *config, snd_config_t *leaf); + int (*snd_config_delete)(snd_config_t *config); + int (*snd_config_delete_compound_members)(const snd_config_t *config); + int (*snd_config_copy)(snd_config_t **dst, snd_config_t *src); + snd_config_type_t (*snd_config_get_type)(const snd_config_t *config); + int (*snd_config_set_id)(snd_config_t *config, const char *id); + int (*snd_config_set_integer)(snd_config_t *config, long value); + int (*snd_config_set_integer64)(snd_config_t *config, long long value); + int (*snd_config_set_real)(snd_config_t *config, double value); + int (*snd_config_set_string)(snd_config_t *config, const char *value); + int (*snd_config_set_ascii)(snd_config_t *config, const char *ascii); + int (*snd_config_set_pointer)(snd_config_t *config, const void *ptr); + int (*snd_config_get_id)(const snd_config_t *config, const char **value); + int (*snd_config_get_integer)(const snd_config_t *config, long *value); + int (*snd_config_get_integer64)(const snd_config_t *config, long long *value); + int (*snd_config_get_real)(const snd_config_t *config, double *value); + int (*snd_config_get_ireal)(const snd_config_t *config, double *value); + int (*snd_config_get_string)(const snd_config_t *config, const char **value); + int (*snd_config_get_ascii)(const snd_config_t *config, char **value); + int (*snd_config_get_pointer)(const snd_config_t *config, const void **value); + snd_config_iterator_t (*snd_config_iterator_first)(const snd_config_t *node); + snd_config_iterator_t (*snd_config_iterator_next)(const snd_config_iterator_t iterator); + snd_config_iterator_t (*snd_config_iterator_end)(const snd_config_t *node); + snd_config_t * (*snd_config_iterator_entry)(const snd_config_iterator_t iterator); + int (*snd_config_test_id)(const snd_config_t *config, const char *id); + int (*snd_names_list)(const char *iface, snd_devname_t **list); + int (*snd_config_get_bool_ascii)(const char *ascii); + int (*snd_config_get_bool)(const snd_config_t *conf); + int (*snd_config_get_ctl_iface_ascii)(const char *ascii); + int (*snd_config_get_ctl_iface)(const snd_config_t *conf); + + /* custom methods */ + int (*setup_fifo)(struct _alsa *, const char *); + +} alsa; + +alsa * g_alsa; + +int APP_CC +g_alsa_init(void); + +int APP_CC +g_alsa_deinit(void); + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/asound.conf posixrdp/posixxrdp.orig/sesman/chansrv/asound.conf --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/asound.conf 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/asound.conf 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,40 @@ +pcm.xrdp { + @args [ FILE RATE ] + @args.FILE { + type string; + default { + @func getenv + vars [ AUDIO_FIFO_PATH ] + default "/dev/null" + } + } + @args.RATE { + type integer; + default { + @func igetenv + vars [ AUDIO_RATE ] + default 44100 + } + } + type plug; + slave.pcm { + type rate; + slave { + pcm { + type file; + slave { pcm { type null; } } + file $FILE; + } + rate $RATE + } + converter "samplerate" + } +} + +pcm.dmixer { type dmix; slave.pcm xrdp; } +pcm.dsp0 { type plug; slave.pcm dmixer; } +ctl.mixer0 { type dmix; slave.pcm xrdp; } +pcm.main { type plug; slave.pcm xrdp; } +ctl.main { type plug; slave.pcm mixer0; } +pcm.!default { type plug; slave.pcm main; } +ctl.!default { type plug; slave.pcm main; } diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/chansrv.c posixrdp/posixxrdp.orig/sesman/chansrv/chansrv.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/chansrv.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/chansrv.c 2010-11-08 09:56:45.000000000 +0100 @@ -17,6 +17,15 @@ Copyright (C) Jay Sorg 2009 */ +#include +#include +#include +#include +#include +#include +#include +#include + #include "arch.h" #include "os_calls.h" #include "thread_calls.h" @@ -26,43 +35,79 @@ #include "sound.h" #include "clipboard.h" #include "devredir.h" +#include "drdynvc.h" #include "list.h" #include "file.h" #include "file_loc.h" +#include "thread_calls.h" +#include "thread_macros.h" +#include "dbg.h" -static struct trans* g_lis_trans = 0; -static struct trans* g_con_trans = 0; -static struct chan_item g_chan_items[32]; -static int g_num_chan_items = 0; -static int g_cliprdr_index = -1; -static int g_rdpsnd_index = -1; -static int g_rdpdr_index = -1; +tc_t g_out_mutex;// = TC_MUTEX_INITIALIZER; +tc_p mutex_out = (tc_p)(&g_out_mutex); +tc_t g_chan_mutex;// = TC_MUTEX_INITIALIZER; +tc_p mutex_chan = (tc_p)NULL; +tc_t g_event_mutex;// = TC_MUTEX_INITIALIZER; +tc_p mutex_event = (tc_p)(&g_event_mutex); +tc_t g_mem_mutex;// = TC_MUTEX_INITIALIZER; +tc_p mutex_mem = (tc_p)(&g_mem_mutex); + +tc_t g_mutattr; +tc_p g_attr = (tc_p)(&g_mutattr); + +static struct trans * g_lis_trans = 0; +static struct trans * g_con_trans = 0; +static struct chan_item g_chan_items[64]; +static ptrdiff_t g_num_chan_items = 0; +static ptrdiff_t g_cliprdr_index = -1; +static ptrdiff_t g_rdpsnd_index = -1; +static ptrdiff_t g_rdpdr_index = -1; +static ptrdiff_t g_drdynvc_index = -1; static tbus g_term_event = 0; static tbus g_thread_done_event = 0; -static int g_use_unix_socket = 0; +static unsigned char g_use_unix_socket = 0; +static unsigned char g_atomic = 0; +static unsigned char verbose = 0; int g_display_num = 0; int g_cliprdr_chan_id = -1; /* cliprdr */ int g_rdpsnd_chan_id = -1; /* rdpsnd */ +int g_audio_input_chan_id = -1; /* audio_input */ int g_rdpdr_chan_id = -1; /* rdpdr */ +int g_drdynvc_chan_id = -1; /* dynamic virtual channels */ /*****************************************************************************/ /* returns error */ -int APP_CC -send_channel_data(int chan_id, char* data, int size) +ptrdiff_t APP_CC +send_channel_data(int chan_id, char * data, size_t size) { - struct stream* s; - int chan_flags; - int total_size; - int sent; - int rv; + struct stream * s = (struct stream *)NULL; + int chan_flags = 0; + ptrdiff_t total_size = 0; + ptrdiff_t sent = 0; + ptrdiff_t rv = 0; + unsigned char tlocked = 0; + + TC_MUTEX_LOCK(mutex_chan); + + if (g_con_trans == NULL || g_con_trans->lock == NULL) { + MDBGLOG("chansrv","ERROR\t[%s()]: g_con_trans is NULL",__func__); + rv = 1; + goto end; + } + else { + TC_MUTEX_LOCK(g_con_trans->lock); + tlocked = 1; + } - s = trans_get_out_s(g_con_trans, 8192); + s = trans_get_out_s(g_con_trans, MAX_STREAM); if (s == 0) { - return 1; + MDBGLOG("chansrv","ERROR\t[%s()]: s is NULL",__func__); + rv = 1; + goto end; } rv = 0; sent = 0; @@ -95,30 +140,133 @@ break; } sent += size; - s = trans_get_out_s(g_con_trans, 8192); + s = trans_get_out_s(g_con_trans, MAX_STREAM); + } + + end:; + if (tlocked) { + TC_MUTEX_UNLOCK(g_con_trans->lock); + tlocked = 0; } + TC_MUTEX_UNLOCK(mutex_chan); return rv; } /*****************************************************************************/ /* returns error */ -static int APP_CC -send_init_response_message(void) +ptrdiff_t APP_CC +send_channel_data_multiple_atomic(int chan_id, unsigned int num, char * datas[], size_t sizes[]) { - struct stream* s; + struct stream * s = (struct stream *)NULL; + int chan_flags = 0; + ptrdiff_t rv = 0; + ptrdiff_t idx = 0; + unsigned char tlocked = 0; + + TC_MUTEX_LOCK(mutex_chan); + + if (g_con_trans == NULL || g_con_trans->lock == NULL) { + rv = 1; + goto end; + } + else { + TC_MUTEX_LOCK(g_con_trans->lock); + tlocked = 1; + } - LOG(1, ("send_init_response_message:")); - s = trans_get_out_s(g_con_trans, 8192); + s = trans_get_out_s(g_con_trans, MAX_STREAM); if (s == 0) { - return 1; + rv = 1; + goto end; + } + rv = 0; + + for (idx = 0; idx < num; idx++) { + + ptrdiff_t total_size = 0; + ptrdiff_t sent = 0; + ptrdiff_t size = 0; + char * data = (char *)NULL; + + size = sizes[idx]; + data = datas[idx]; + + total_size = size; + while (sent < total_size) { + size = MIN(1600, (total_size - sent)); + chan_flags = 0; + if (sent == 0) { + chan_flags |= 1; /* first */ + } + if (size + sent == total_size) { + chan_flags |= 2; /* last */ + } + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 8 + 8 + 2 + 2 + 2 + 4 + size); /* size */ + out_uint32_le(s, 8); /* msg id */ + out_uint32_le(s, 8 + 2 + 2 + 2 + 4 + size); /* size */ + out_uint16_le(s, chan_id); + out_uint16_le(s, chan_flags); + out_uint16_le(s, size); + out_uint32_le(s, total_size); + out_uint8a(s, data + sent, size); + s_mark_end(s); + rv = trans_force_write(g_con_trans); + if (rv != 0) { + break; + } + sent += size; + s = trans_get_out_s(g_con_trans, MAX_STREAM); + } + + } + + end:; + if (tlocked) { + TC_MUTEX_UNLOCK(g_con_trans->lock); + tlocked = 0; } - out_uint32_le(s, 0); /* version */ - out_uint32_le(s, 8 + 8); /* size */ - out_uint32_le(s, 2); /* msg id */ - out_uint32_le(s, 8); /* size */ - s_mark_end(s); - return trans_force_write(g_con_trans); + TC_MUTEX_UNLOCK(mutex_chan); + return rv; +} + +/*****************************************************************************/ +/* returns error */ +static int APP_CC +send_init_response_message(void) +{ + int rv = 0; + unsigned char tlocked = 0; + struct stream * s = (struct stream *)NULL; + TC_MUTEX_LOCK(mutex_chan); + if (g_con_trans == NULL || g_con_trans->lock == NULL) { + rv = 1; + goto end; + } + else { + TC_MUTEX_LOCK(g_con_trans->lock); + tlocked = 1; + } + s = trans_get_out_s(g_con_trans, MAX_STREAM); + if (s == NULL) { + rv = 1; + } + else { + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 8 + 8); /* size */ + out_uint32_le(s, 2); /* msg id */ + out_uint32_le(s, 8); /* size */ + s_mark_end(s); + rv = trans_force_write(g_con_trans); + } + end:; + if (tlocked) { + TC_MUTEX_UNLOCK(g_con_trans->lock); + tlocked = 0; + } + TC_MUTEX_UNLOCK(mutex_chan); + return rv; } /*****************************************************************************/ @@ -126,20 +274,45 @@ static int APP_CC send_channel_setup_response_message(void) { - struct stream* s; + int rv = 0; + unsigned char tlocked = 0; + struct stream * s = NULL; LOG(10, ("send_channel_setup_response_message:")); - s = trans_get_out_s(g_con_trans, 8192); + MDBGLOG("chansrv","INFO\t[%s()]: called",__func__); + + TC_MUTEX_LOCK(mutex_chan); + + if (g_con_trans == NULL || g_con_trans->lock == NULL) { + rv = 1; + goto end; + } + else { + TC_MUTEX_LOCK(g_con_trans->lock); + tlocked = 1; + } + + s = trans_get_out_s(g_con_trans, MAX_STREAM); if (s == 0) { - return 1; + rv = 1; + } + else { + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 8 + 8); /* size */ + out_uint32_le(s, 4); /* msg id */ + out_uint32_le(s, 8); /* size */ + s_mark_end(s); + rv = trans_force_write(g_con_trans); } - out_uint32_le(s, 0); /* version */ - out_uint32_le(s, 8 + 8); /* size */ - out_uint32_le(s, 4); /* msg id */ - out_uint32_le(s, 8); /* size */ - s_mark_end(s); - return trans_force_write(g_con_trans); + + end:; + if (tlocked) { + TC_MUTEX_UNLOCK(g_con_trans->lock); + tlocked = 0; + } + TC_MUTEX_UNLOCK(mutex_chan); + return rv; } /*****************************************************************************/ @@ -147,20 +320,46 @@ static int APP_CC send_channel_data_response_message(void) { - struct stream* s; + int rv = 0; + unsigned char tlocked = 0; + struct stream * s = NULL; - LOG(10, ("send_channel_data_response_message:")); - s = trans_get_out_s(g_con_trans, 8192); - if (s == 0) + if (verbose) { + MDBGLOG("chansrv","INFO\t[%s()]: called",__func__); + //LOG(10, ("send_channel_data_response_message:")); + } + + TC_MUTEX_LOCK(mutex_chan); + + if (g_con_trans == NULL || g_con_trans->lock == NULL) { + rv = 1; + goto end; + } + else { + TC_MUTEX_LOCK(g_con_trans->lock); + tlocked = 1; + } + + s = trans_get_out_s(g_con_trans, MAX_STREAM); + if (s == NULL) { - return 1; + rv = 1; + } + else { + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 8 + 8); /* size */ + out_uint32_le(s, 6); /* msg id */ + out_uint32_le(s, 8); /* size */ + s_mark_end(s); + rv = trans_force_write(g_con_trans); + } + + end:; + if (tlocked) { + TC_MUTEX_UNLOCK(g_con_trans->lock); } - out_uint32_le(s, 0); /* version */ - out_uint32_le(s, 8 + 8); /* size */ - out_uint32_le(s, 6); /* msg id */ - out_uint32_le(s, 8); /* size */ - s_mark_end(s); - return trans_force_write(g_con_trans); + TC_MUTEX_UNLOCK(mutex_chan); + return rv; } /*****************************************************************************/ @@ -168,8 +367,19 @@ static int APP_CC process_message_init(struct stream* s) { + unsigned char tunlocked = 0; LOG(10, ("process_message_init:")); + MDBGLOG("chansrv","INFO\t[%s()]: called",__func__); + if (g_con_trans != NULL && g_con_trans->lock != NULL) { + TC_MUTEX_UNLOCK(g_con_trans->lock); + tunlocked = 1; + } + TC_MUTEX_UNLOCK(mutex_chan); return send_init_response_message(); + TC_MUTEX_LOCK(mutex_chan); + if (tunlocked) { + TC_MUTEX_LOCK(g_con_trans->lock); + } } /*****************************************************************************/ @@ -177,10 +387,13 @@ static int APP_CC process_message_channel_setup(struct stream* s) { - int num_chans; - int index; - int rv; - struct chan_item* ci; + int num_chans = 0; + ptrdiff_t index = 0; + int rv = 0; + unsigned char tunlocked = 0; + struct chan_item * ci = (struct chan_item *)NULL; + + //TC_MUTEX_LOCK(mutex_chan); g_num_chan_items = 0; g_cliprdr_index = -1; @@ -188,10 +401,14 @@ g_rdpdr_index = -1; g_cliprdr_chan_id = -1; g_rdpsnd_chan_id = -1; + g_audio_input_chan_id = -1; g_rdpdr_chan_id = -1; - LOG(10, ("process_message_channel_setup:")); + g_drdynvc_chan_id = -1; + in_uint16_le(s, num_chans); LOG(10, ("process_message_channel_setup: num_chans %d", num_chans)); + MDBGLOG("chansrv", "INFO\t[%s()]: num_chans = %d", __func__, num_chans); + for (index = 0; index < num_chans; index++) { ci = &(g_chan_items[g_num_chan_items]); @@ -199,8 +416,8 @@ in_uint8a(s, ci->name, 8); in_uint16_le(s, ci->id); in_uint16_le(s, ci->flags); - LOG(10, ("process_message_channel_setup: chan name '%s' " - "id %d flags %8.8x", ci->name, ci->id, ci->flags)); + //LOG(10, ("process_message_channel_setup: channel name = '%s'; id = %d; flags = %8.8x", ci->name, ci->id, ci->flags)); + MDBGLOG("chansrv", "INFO\t[%s()]: channel name = \"%s\"; id = %d; flags = 0x%8.8x", __func__, ci->name, ci->id, ci->flags); if (g_strcasecmp(ci->name, "cliprdr") == 0) { g_cliprdr_index = g_num_chan_items; @@ -216,9 +433,23 @@ g_rdpdr_index = g_num_chan_items; g_rdpdr_chan_id = ci->id; } + else if (g_strcasecmp(ci->name, "drdynvc") == 0) + { + g_drdynvc_index = g_num_chan_items; + g_drdynvc_chan_id = ci->id; + } g_num_chan_items++; } + if (g_con_trans != NULL && g_con_trans->lock != NULL) { + TC_MUTEX_UNLOCK(g_con_trans->lock); + tunlocked = 1; + } + TC_MUTEX_UNLOCK(mutex_chan); rv = send_channel_setup_response_message(); + TC_MUTEX_LOCK(mutex_chan); + if (tunlocked) { + TC_MUTEX_LOCK(g_con_trans->lock); + } if (g_cliprdr_index >= 0) { clipboard_init(); @@ -229,29 +460,50 @@ } if (g_rdpdr_index >= 0) { - dev_redir_init(); + rdpdr_init(); + } + if (g_drdynvc_index >= 0) + { + drdynvc_init(); } return rv; } -/*****************************************************************************/ -/* returns error */ +/***************************************************************************** + * + * - returns error + * - caller must hold the "g_con_trans->lock" mutex + * + *****************************************************************************/ static int APP_CC process_message_channel_data(struct stream* s) { - int chan_id; - int chan_flags; - int rv; - int length; - int total_length; + int rv = 0; + int chan_id = 0; + int chan_flags = 0; + ptrdiff_t length = 0; + ptrdiff_t total_length = 0; + unsigned char tunlocked = 0; + + if (verbose) { + MDBGLOG("chansrv","INFO\t[%s()]: called (s = %p)",__func__,s); + } in_uint16_le(s, chan_id); in_uint16_le(s, chan_flags); in_uint16_le(s, length); in_uint32_le(s, total_length); - LOG(10, ("process_message_channel_data: chan_id %d " - "chan_flags %d", chan_id, chan_flags)); + LOG(10, ("process_message_channel_data: chan_id = %d; chan_flags = %d", chan_id, chan_flags)); + if (g_con_trans != NULL && g_con_trans->lock != NULL) { + TC_MUTEX_UNLOCK(g_con_trans->lock); + tunlocked = 1; + } + TC_MUTEX_UNLOCK(mutex_chan); rv = send_channel_data_response_message(); + TC_MUTEX_LOCK(mutex_chan); + if (tunlocked) { + TC_MUTEX_LOCK(g_con_trans->lock); + } if (rv == 0) { if (chan_id == g_cliprdr_chan_id) @@ -264,7 +516,11 @@ } else if (chan_id == g_rdpdr_chan_id) { - rv = dev_redir_data_in(s, chan_id, chan_flags, length, total_length); + rv = rdpdr_data_in(s, chan_id, chan_flags, length, total_length); + } + else if (chan_id == g_drdynvc_chan_id) + { + rv = drdynvc_data_in(s, chan_id, chan_flags, length, total_length); } } return rv; @@ -272,10 +528,13 @@ /*****************************************************************************/ /* returns error */ -static int APP_CC +static inline int APP_CC process_message_channel_data_response(struct stream* s) { - LOG(10, ("process_message_channel_data_response:")); + if (verbose) { + LOG(10, ("process_message_channel_data_response:")); + MDBGLOG("chansrv","INFO\t[%s()]: called",__func__); + } return 0; } @@ -284,21 +543,44 @@ static int APP_CC process_message(void) { - struct stream* s; - int size; - int id; - int rv; - char* next_msg; + struct stream* s = (struct stream *)NULL; + int size = 0; + int id = 0; + int rv = 0; + unsigned char tlocked = 0; + char* next_msg = (char *)NULL; + if (verbose) { + MDBGLOG("chansrv","INFO\t[%s()]: called",__func__); + } + + TC_MUTEX_LOCK(mutex_chan); + + TC_MUTEX_LOCK(mutex_event); if (g_con_trans == 0) { + TC_MUTEX_UNLOCK(mutex_event); return 1; } - s = trans_get_in_s(g_con_trans); + else { + if (g_con_trans->lock != NULL) { + TC_MUTEX_LOCK(g_con_trans->lock); + tlocked = 1; + } + s = trans_get_in_s(g_con_trans); + } if (s == 0) { + if (tlocked) { + TC_MUTEX_UNLOCK(g_con_trans->lock); + tlocked = 0; + } + TC_MUTEX_UNLOCK(mutex_event); return 1; } + else { + TC_MUTEX_UNLOCK(mutex_event); + } rv = 0; while (s_check_rem(s, 8)) { @@ -321,47 +603,79 @@ rv = process_message_channel_data_response(s); break; default: - LOG(0, ("process_message: error in process_message " - "unknown msg %d", id)); - break; + LOG(0, ("[xdrp-chansrv]->process_message(): !!! ERROR (unknown msg = %d) !!!", id)); + MDBGLOG("chansrv", "WARNING\t[%s()]: unknown msg = %d", __func__, id); + break; } - if (rv != 0) - { + if (rv != 0) { break; } - s->p = next_msg; + else { + s->p = next_msg; + } + } + end:; + if (tlocked) { + TC_MUTEX_UNLOCK(g_con_trans->lock); + tlocked = 0; } + TC_MUTEX_UNLOCK(mutex_chan); return rv; } /*****************************************************************************/ /* returns error */ -int DEFAULT_CC +size_t DEFAULT_CC my_trans_data_in(struct trans* trans) { - struct stream* s; - int id; - int size; - int error; + struct stream * s = (struct stream *)NULL; + int id = 0; + ptrdiff_t size = 0; + size_t error = 0; if (trans == 0) { return 0; } + TC_MUTEX_LOCK(mutex_event); if (trans != g_con_trans) { + TC_MUTEX_UNLOCK(mutex_event); return 1; } - LOG(10, ("my_trans_data_in:")); + else { + TC_MUTEX_UNLOCK(mutex_event); + } + if (verbose) { + MDBGLOG("chansrv", "INFO\t[%s()]: called (trans->sck = %d; trans->lock = %p)", __func__, trans->sck, trans->lock); + } + if (trans != NULL && trans->lock == NULL) { + tc_t mattr; + tc_p pattr = &mattr; + g_memset(pattr,0,sizeof(tc_t)); + TC_MUTATTR_INIT(pattr); + TC_MUTATTR_SETTYPE(pattr,TC_MUTEX_ERRORCHECK); + TC_MUTATTR_SETPSHARED(pattr,TC_PROCESS_SHARED); + trans->lock = (tc_p)g_malloc(sizeof(tc_t), 1); + TC_MUTEX_INIT(trans->lock, pattr); + } + TC_MUTEX_LOCK(trans->lock); s = trans_get_in_s(trans); in_uint32_le(s, id); in_uint32_le(s, size); + if (verbose) { + MDBGLOG("chansrv", "INFO\t[%s()]: id = %d", __func__, id); + } error = trans_force_read(trans, size - 8); if (error == 0) { /* here, the entire message block is read in, process it */ error = process_message(); } + TC_MUTEX_UNLOCK(trans->lock); + if (verbose) { + MDBGLOG("chansrv", "INFO\t[%s()]: done.", __func__); + } return error; } @@ -373,25 +687,58 @@ { return 1; } + TC_MUTEX_LOCK(mutex_event); if (trans != g_lis_trans) { + TC_MUTEX_UNLOCK(mutex_event); return 1; } if (g_con_trans != 0) /* if already set, error */ { + TC_MUTEX_UNLOCK(mutex_event); return 1; } if (new_trans == 0) { + TC_MUTEX_UNLOCK(mutex_event); return 1; } LOG(10, ("my_trans_conn_in:")); + if (verbose) { + MDBGLOG("chansrv", "INFO\t[%s()]: called", __func__); + } g_con_trans = new_trans; + if (g_con_trans != NULL && g_con_trans->lock == NULL) { + tc_t mattr; + tc_p pattr = &mattr; + g_memset(pattr,0,sizeof(tc_t)); + TC_MUTATTR_INIT(pattr); + TC_MUTATTR_SETTYPE(pattr,TC_MUTEX_ERRORCHECK); + TC_MUTATTR_SETPSHARED(pattr,TC_PROCESS_SHARED); + g_con_trans->lock = (tc_p)g_malloc(sizeof(tc_t), 1); + TC_MUTEX_INIT(g_con_trans->lock, pattr); + } + TC_MUTEX_LOCK(g_con_trans->lock); g_con_trans->trans_data_in = my_trans_data_in; g_con_trans->header_size = 8; + TC_MUTEX_UNLOCK(g_con_trans->lock); /* stop listening */ - trans_delete(g_lis_trans); - g_lis_trans = 0; + if (g_lis_trans == NULL || g_lis_trans->lock == NULL) { + trans_delete(g_lis_trans); + g_lis_trans = 0; + } + else { + tc_p tp = g_lis_trans->lock; + TC_MUTEX_LOCK(tp); + trans_delete(g_lis_trans); + g_lis_trans = 0; + TC_MUTEX_UNLOCK(tp); + g_free(tp); + } + TC_MUTEX_UNLOCK(mutex_event); + if (verbose) { + MDBGLOG("chansrv", "INFO\t[%s()]: done.", __func__); + } return 0; } @@ -400,109 +747,269 @@ setup_listen(void) { char port[256]; - int error; + int error = 0; + int res = 0; + + g_memset(port,0,sizeof(port)); + TC_MUTEX_LOCK(mutex_event); if (g_lis_trans != 0) { + unsigned char tlock = 0; + if (g_lis_trans->lock != NULL) { + TC_MUTEX_LOCK(g_lis_trans->lock); + tlock = 1; + } trans_delete(g_lis_trans); + if (tlock > 0) { + TC_MUTEX_UNLOCK(g_lis_trans->lock); + } } if (g_use_unix_socket) { - g_lis_trans = trans_create(2, 8192, 8192); + tc_t mattr; + tc_p pattr = &mattr; + g_memset(pattr,0,sizeof(tc_t)); + TC_MUTATTR_INIT(pattr); + TC_MUTATTR_SETTYPE(pattr,TC_MUTEX_ERRORCHECK); + TC_MUTATTR_SETPSHARED(pattr,TC_PROCESS_SHARED); + g_lis_trans = trans_create(2, MAX_STREAM, MAX_STREAM); + g_lis_trans->lock = (tc_p)g_malloc(sizeof(tc_t), 1); + TC_MUTEX_INIT(g_lis_trans->lock, pattr); g_snprintf(port, 255, "/tmp/xrdp_chansrv_socket_%d", 7200 + g_display_num); } else { - g_lis_trans = trans_create(1, 8192, 8192); + tc_t mattr; + tc_p pattr = &mattr; + g_memset(pattr,0,sizeof(tc_t)); + TC_MUTATTR_INIT(pattr); + TC_MUTATTR_SETTYPE(pattr,TC_MUTEX_ERRORCHECK); + TC_MUTATTR_SETPSHARED(pattr,TC_PROCESS_SHARED); + g_lis_trans = trans_create(1, MAX_STREAM, MAX_STREAM); + g_lis_trans->lock = (tc_p)g_malloc(sizeof(tc_t), 1); + TC_MUTEX_INIT(g_lis_trans->lock, pattr); g_snprintf(port, 255, "%d", 7200 + g_display_num); } + TC_MUTEX_LOCK(g_lis_trans->lock); g_lis_trans->trans_conn_in = my_trans_conn_in; error = trans_listen(g_lis_trans, port); + TC_MUTEX_UNLOCK(g_lis_trans->lock); + TC_MUTEX_UNLOCK(mutex_event); if (error != 0) { LOG(0, ("setup_listen: trans_listen failed for port %s", port)); - return 1; + MDBGLOG("chansrv", "ERROR\t[%s()]: trans_listen() failed for port \"%s\"", __func__, port); + res = 1; } - return 0; + return res; } /*****************************************************************************/ THREAD_RV THREAD_CC channel_thread_loop(void* in_val) { - tbus objs[32]; - int num_objs; - int timeout; - int error; - THREAD_RV rv; + tbus objs[64]; + int num_objs = 0; + int timeout = 0; + int error = 0; + int elocked = 0; + int mlocked = 0; + THREAD_RV rv = 0; LOG(1, ("channel_thread_loop: thread start")); + MDBGLOG("chansrv", "INFO\t[%s()]: thread start [pid = %d, tid = %d]", __func__,g_getpid(),g_gettid()); + + g_memset(objs,0,sizeof(objs)); rv = 0; + + TC_MUTEX_LOCK(mutex_chan); + mlocked = 1; error = setup_listen(); if (error == 0) { timeout = 0; num_objs = 0; + + TC_MUTEX_LOCK(mutex_event); + elocked = 1; objs[num_objs] = g_term_event; num_objs++; - trans_get_wait_objs(g_lis_trans, objs, &num_objs, &timeout); + if (g_lis_trans != NULL && g_lis_trans->lock != NULL) { + TC_MUTEX_LOCK(g_lis_trans->lock); + trans_get_wait_objs(g_lis_trans, objs, &num_objs, &timeout); + TC_MUTEX_UNLOCK(g_lis_trans->lock); + } + else if (g_lis_trans != NULL) { + trans_get_wait_objs(g_lis_trans, objs, &num_objs, &timeout); + } + TC_MUTEX_UNLOCK(mutex_event); + elocked = 0; + + TC_MUTEX_UNLOCK(mutex_chan); + mlocked = 0; + while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) { if (g_is_wait_obj_set(g_term_event)) { LOG(0, ("channel_thread_loop: g_term_event set")); + MDBGLOG("chansrv", "INFO\t[%s()]: g_term_event set", __func__); + clipboard_deinit(); sound_deinit(); - dev_redir_deinit(); - break; + rdpdr_deinit(); + drdynvc_deinit(); + + break; } + TC_MUTEX_LOCK(mutex_event); if (g_lis_trans != 0) { + TC_MUTEX_UNLOCK(mutex_event); if (trans_check_wait_objs(g_lis_trans) != 0) { LOG(0, ("channel_thread_loop: trans_check_wait_objs error")); + MDBGLOG("chansrv", "WARNING\t[%s()]: ERROR in trans_check_wait_objs()", __func__); } + TC_MUTEX_LOCK(mutex_event); } if (g_con_trans != 0) { - if (trans_check_wait_objs(g_con_trans) != 0) + int tres = 0; + TC_MUTEX_UNLOCK(mutex_event); + tres = trans_check_wait_objs(g_con_trans); + if (tres != 0) { - LOG(0, ("channel_thread_loop: " - "trans_check_wait_objs error resetting")); + + LOG(0, ("channel_thread_loop: trans_check_wait_objs error resetting")); + MDBGLOG("chansrv","WARNING\t[%s()]: trans_check_wait_objs() returned error 0x%8.8x; now resetting", __func__, tres); + clipboard_deinit(); sound_deinit(); - dev_redir_deinit(); + rdpdr_deinit(); + drdynvc_deinit(); + + TC_MUTEX_LOCK(mutex_chan); + mlocked = 1; + /* delete g_con_trans */ - trans_delete(g_con_trans); - g_con_trans = 0; + TC_MUTEX_LOCK(mutex_event); + elocked = 1; + if (g_con_trans != 0) { + unsigned char tlock = 0; + if (g_con_trans->lock != NULL) { + TC_MUTEX_LOCK(g_con_trans->lock); + tlock = 1; + } + trans_delete(g_con_trans); + if (tlock > 0) { + TC_MUTEX_UNLOCK(g_con_trans->lock); + } + g_con_trans = 0; + } + TC_MUTEX_UNLOCK(mutex_event); + elocked = 0; /* create new listener */ error = setup_listen(); + + TC_MUTEX_UNLOCK(mutex_chan); + mlocked = 0; + if (error != 0) { break; } } } + else { + TC_MUTEX_UNLOCK(mutex_event); + } + clipboard_check_wait_objs(); sound_check_wait_objs(); - dev_redir_check_wait_objs(); + rdpdr_check_wait_objs(); + drdynvc_check_wait_objs(); + + TC_MUTEX_LOCK(mutex_chan); + mlocked = 1; + timeout = 0; num_objs = 0; + TC_MUTEX_LOCK(mutex_event); + elocked = 1; objs[num_objs] = g_term_event; num_objs++; - trans_get_wait_objs(g_lis_trans, objs, &num_objs, &timeout); - trans_get_wait_objs(g_con_trans, objs, &num_objs, &timeout); + { + unsigned char tlock = 0; + if (g_lis_trans != NULL && g_lis_trans->lock != NULL) { + TC_MUTEX_LOCK(g_lis_trans->lock); + tlock = 1; + } + trans_get_wait_objs(g_lis_trans, objs, &num_objs, &timeout); + if (tlock > 0) { + TC_MUTEX_UNLOCK(g_lis_trans->lock); + } + tlock = 0; + if (g_con_trans != NULL && g_con_trans->lock != NULL) { + TC_MUTEX_LOCK(g_con_trans->lock); + tlock = 1; + } + trans_get_wait_objs(g_con_trans, objs, &num_objs, &timeout); + if (tlock > 0) { + TC_MUTEX_UNLOCK(g_con_trans->lock); + } + } + TC_MUTEX_UNLOCK(mutex_event); + elocked = 0; clipboard_get_wait_objs(objs, &num_objs, &timeout); sound_get_wait_objs(objs, &num_objs, &timeout); - dev_redir_get_wait_objs(objs, &num_objs, &timeout); + rdpdr_get_wait_objs(objs, &num_objs, &timeout); + drdynvc_get_wait_objs(objs, &num_objs, &timeout); + + TC_MUTEX_UNLOCK(mutex_chan); + mlocked = 0; } } - trans_delete(g_lis_trans); + else if (mlocked > 0) { + TC_MUTEX_UNLOCK(mutex_chan); + mlocked = 0; + } + + TC_MUTEX_LOCK(mutex_chan); + mlocked = 1; + + TC_MUTEX_LOCK(mutex_event); + elocked = 1; + if (g_lis_trans != NULL && g_lis_trans->lock != NULL) { + TC_MUTEX_LOCK(g_lis_trans->lock); + trans_delete(g_lis_trans); + TC_MUTEX_UNLOCK(g_lis_trans->lock); + } + else if (g_lis_trans != NULL) { + trans_delete(g_lis_trans); + } g_lis_trans = 0; - trans_delete(g_con_trans); + + if (g_con_trans != NULL && g_con_trans->lock != NULL) { + TC_MUTEX_LOCK(g_con_trans->lock); + trans_delete(g_con_trans); + TC_MUTEX_UNLOCK(g_con_trans->lock); + } + else if (g_con_trans != NULL) { + trans_delete(g_con_trans); + } g_con_trans = 0; + LOG(0, ("channel_thread_loop: thread stop")); + MDBGLOG("chansrv", "SIGNAL\t[%s()]: thread stop", __func__); g_set_wait_obj(g_thread_done_event); + TC_MUTEX_UNLOCK(mutex_event); + elocked = 0; + + TC_MUTEX_UNLOCK(mutex_chan); + mlocked = 0; + return rv; } @@ -510,66 +1017,84 @@ void DEFAULT_CC term_signal_handler(int sig) { - LOG(1, ("term_signal_handler: got signal %d", sig)); + //LOG(1, ("term_signal_handler: got signal %d", sig)); + MDBGLOG("chansrv", "SIGNAL\t[%s()]: received signal %d", __func__, sig); + //TC_MUTEX_LOCK(mutex_event); g_set_wait_obj(g_term_event); + //TC_MUTEX_UNLOCK(mutex_event); } /*****************************************************************************/ void DEFAULT_CC nil_signal_handler(int sig) { - LOG(1, ("nil_signal_handler: got signal %d", sig)); + //LOG(1, ("nil_signal_handler: got signal %d", sig)); + MDBGLOG("chansrv", "SIGNAL\t[%s()]: received signal %d", __func__, sig); } /*****************************************************************************/ static int APP_CC -get_display_num_from_display(char* display_text) +get_display_num_from_display(char * display_text) { - int index; - int mode; - int host_index; - int disp_index; - int scre_index; - char host[256]; - char disp[256]; - char scre[256]; - - index = 0; - host_index = 0; - disp_index = 0; - scre_index = 0; - mode = 0; - while (display_text[index] != 0) - { - if (display_text[index] == ':') - { - mode = 1; + ptrdiff_t index = 0; + int mode = 0; + ptrdiff_t host_index = 0; + ptrdiff_t disp_index = 0; + ptrdiff_t scre_index = 0; + char host[256] = ""; + char disp[256] = ""; + char scre[256] = ""; + ptrdiff_t bcnt = 0; + ptrdiff_t ccnt = 0; + ptrdiff_t first_brack_pos = 0; + ptrdiff_t final_brack_pos = 0; + ptrdiff_t final_colon_pos = 0; + ptrdiff_t final_dot_pos = 0; + char * tmp = (char *)NULL; + char * pch = (char *)NULL; + char * first_brack = (char *)NULL; + char * final_brack = (char *)NULL; + char * final_colon = (char *)NULL; + char * final_dot = (char *)NULL; + + g_memset(host,0,256); + g_memset(disp,0,256); + g_memset(scre,0,256); + + if (display_text[0] == '[') { + first_brack_pos = 1; + final_brack = strrchr(display_text, ']'); + if (final_brack != NULL) { + final_brack_pos = final_brack - display_text + 1; } - else if (display_text[index] == '.') - { - mode = 2; - } - else if (mode == 0) - { - host[host_index] = display_text[index]; - host_index++; - } - else if (mode == 1) - { - disp[disp_index] = display_text[index]; - disp_index++; + } + + final_colon = strrchr(display_text, ':'); + if (final_colon != NULL) { + final_colon_pos = (final_colon - display_text) + 1; + } + + final_dot = strrchr(final_colon, '.'); + if (final_dot != NULL) { + final_dot_pos = (final_dot - display_text) + 1; + } + + if (final_colon_pos > 1) { + g_snprintf(host, (final_colon_pos - 1), "%s", display_text); + } + + if (final_colon != NULL) { + if (((final_dot_pos > 0) && (final_colon_pos > 0)) && ((final_dot_pos - (final_colon_pos + 1)) > 1)) { + g_snprintf(disp, (final_dot_pos - final_colon_pos), "%s", final_colon + 1); } - else if (mode == 2) - { - scre[scre_index] = display_text[index]; - scre_index++; + if (final_dot_pos > 0) { + g_sprintf(scre, "%s", final_dot + 1); } - index++; } - host[host_index] = 0; - disp[disp_index] = 0; - scre[scre_index] = 0; + + TC_MUTEX_LOCK(mutex_event); g_display_num = g_atoi(disp); + TC_MUTEX_UNLOCK(mutex_event); return 0; } @@ -577,8 +1102,10 @@ int APP_CC main_cleanup(void) { + TC_MUTEX_LOCK(mutex_event); g_delete_wait_obj(g_term_event); g_delete_wait_obj(g_thread_done_event); + TC_MUTEX_UNLOCK(mutex_event); g_deinit(); /* os_calls */ return 0; } @@ -587,34 +1114,38 @@ static int APP_CC read_ini(void) { - char filename[256]; - struct list* names; - struct list* values; - char* name; - char* value; - int index; + char filename[256] = ""; + struct list* names = (struct list *)NULL; + struct list* values = (struct list *)NULL; + char* name = (char *)NULL; + char* value = (char *)NULL; + ptrdiff_t index = 0; + + g_memset(filename,0,(sizeof(char) * 256)); names = list_create(); names->auto_free = 1; values = list_create(); values->auto_free = 1; + + TC_MUTEX_LOCK(mutex_chan); + g_use_unix_socket = 0; g_snprintf(filename, 255, "%s/sesman.ini", XRDP_CFG_PATH); - if (file_by_name_read_section(filename, "Globals", names, values) == 0) - { - for (index = 0; index < names->count; index++) - { + if (file_by_name_read_section(filename, "Globals", names, values) == 0) { + for (index = 0; index < names->count; index++) { name = (char*)list_get_item(names, index); value = (char*)list_get_item(values, index); - if (g_strcasecmp(name, "ListenAddress") == 0) - { - if (g_strcasecmp(value, "127.0.0.1") == 0) - { - g_use_unix_socket = 1; - } + if (g_strcasecmp(name, "ListenAddress") == 0) { + if ((value == NULL) || (g_strlen(value) < 1) || (g_strcasecmp(value, "socket") == 0) || (g_strcasecmp(value, "localhost") == 0) || (g_strcasecmp(value, "") == 0) || (g_strchr(value, '/') != NULL)) { + g_use_unix_socket = 1; + } } } } + + TC_MUTEX_UNLOCK(mutex_chan); + list_delete(names); list_delete(values); return 0; @@ -624,33 +1155,105 @@ int DEFAULT_CC main(int argc, char** argv) { - int pid; - char text[256]; - char* display_text; + int pid = 0; + char text[256] = ""; + char* display_text = (char *)NULL; + char* username_text = (char *)NULL; + glob_t pglob; + ptrdiff_t idx = 0; + unsigned char elocked = 0; + uid_t tuid = 0; + gid_t tgid = 0; + struct passwd * pw = (struct passwd *)NULL; + + g_attr = &g_mutattr; + g_memset(g_attr,0,sizeof(tc_t)); + TC_MUTATTR_INIT(g_attr); + TC_MUTATTR_SETTYPE(g_attr, TC_MUTEX_ERRORCHECK); + TC_MUTATTR_SETPSHARED(g_attr, TC_PROCESS_SHARED); + + TC_MUTEX_INIT(mutex_event, g_attr); + TC_MUTEX_INIT(mutex_mem, g_attr); + + g_memset(text,0,sizeof(char) * 256); + g_memset(&pglob,0,sizeof(glob_t)); + + if (mutex_chan == NULL) { + tc_t mattr; + tc_p pattr = &mattr; + g_memset(pattr,0,sizeof(tc_t)); + TC_MUTATTR_INIT(pattr); + TC_MUTATTR_SETTYPE(pattr,TC_MUTEX_ERRORCHECK); + TC_MUTATTR_SETPSHARED(pattr,TC_PROCESS_SHARED); + TC_MUTEX_INIT(mutex_chan,pattr); + TC_MUTEX_INIT(&g_out_mutex,pattr); + } + TC_MUTEX_LOCK(mutex_chan); g_init(); /* os_calls */ read_ini(); pid = g_getpid(); + LOG(1, ("main: app started pid %d(0x%8.8x)", pid, pid)); + MDBGLOG("chansrv", "INFO\t[%s()]: xrdp-chansrv started (pid = %d)", __func__, pid); + + /* set up signal handlers */ g_signal_kill(term_signal_handler); /* SIGKILL */ g_signal_terminate(term_signal_handler); /* SIGTERM */ g_signal_user_interrupt(term_signal_handler); /* SIGINT */ g_signal_pipe(nil_signal_handler); /* SIGPIPE */ + + glob("/tmp/taskq_*.log",GLOB_NOSORT,NULL,&pglob); + for (idx = 0; idx < pglob.gl_pathc; idx++) { + unlink(pglob.gl_pathv[idx]); + } + + username_text = g_getenv("USER"); display_text = g_getenv("DISPLAY"); + + pw = getpwnam((const char *)username_text); + tuid = pw->pw_uid; + tgid = pw->pw_gid; + setgid(tgid); + setuid(tuid); + LOG(1, ("main: DISPLAY env var set to %s", display_text)); + MDBGLOG("chansrv", "INFO\t[%s()]: DISPLAY env var set to \"%s\"", __func__, display_text); get_display_num_from_display(display_text); - if (g_display_num == 0) - { + TC_MUTEX_LOCK(mutex_event); + if (g_display_num == 0) { LOG(0, ("main: error, display is zero")); + TC_MUTEX_UNLOCK(mutex_event); return 1; } LOG(1, ("main: using DISPLAY %d", g_display_num)); + MDBGLOG("chansrv", "INFO\t[%s()]: using DISPLAY \"%d\"", __func__, g_display_num); g_snprintf(text, 255, "xrdp_chansrv_%8.8x_main_term", pid); g_term_event = g_create_wait_obj(text); g_snprintf(text, 255, "xrdp_chansrv_%8.8x_thread_done", pid); g_thread_done_event = g_create_wait_obj(text); + TC_MUTEX_UNLOCK(mutex_event); + + { + char tpid[6] = ""; + g_snprintf(tpid,6,"%d",g_getpid()); + g_setenv("PULSE_PROP_application.name","xrdp",1); + g_setenv("PULSE_PROP_application.icon_name","xrdp",1); + g_setenv("PULSE_PROP_media.role","event",1); + g_setenv("PULSE_PROP_application.process.user",username_text,1); + g_setenv("PULSE_PROP_application.process.id",tpid,1); + g_setenv("PULSE_PROP_application.process.binary","xrdp-chansrv",1); + g_setenv("PULSE_PROP_window.x11.display",display_text,1); + } + + + g_iconv_init(); + + TC_MUTEX_UNLOCK(mutex_chan); + tc_thread_create(channel_thread_loop, 0); - while (!g_is_wait_obj_set(g_term_event)) + MDBGLOG("chansrv","INFO\t[%s()]: locked .",__func__); + while (g_term_event > 0 && !g_is_wait_obj_set(g_term_event)) { if (g_obj_wait(&g_term_event, 1, 0, 0, 0) != 0) { @@ -658,7 +1261,7 @@ break; } } - while (!g_is_wait_obj_set(g_thread_done_event)) + while (g_thread_done_event > 0 && !g_is_wait_obj_set(g_thread_done_event)) { /* wait for thread to exit */ if (g_obj_wait(&g_thread_done_event, 1, 0, 0, 0) != 0) @@ -667,8 +1270,15 @@ break; } } + + TC_MUTEX_LOCK(mutex_chan); + + g_iconv_end(); /* cleanup */ main_cleanup(); + + TC_MUTEX_UNLOCK(mutex_chan); + LOG(1, ("main: app exiting pid %d(0x%8.8x)", pid, pid)); return 0; } diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/chansrv.h posixrdp/posixxrdp.orig/sesman/chansrv/chansrv.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/chansrv.h 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/chansrv.h 2010-11-08 09:56:45.000000000 +0100 @@ -2,8 +2,13 @@ #if !defined(CHANSRV_H) #define CHANSRV_H +#include +#include #include "arch.h" #include "parse.h" +#include "thread_calls.h" +#include "thread_macros.h" +#include "dbg.h" struct chan_item { @@ -12,13 +17,11 @@ char name[16]; }; -int APP_CC -send_channel_data(int chan_id, char* data, int size); -int APP_CC -main_cleanup(void); - -#define LOG_LEVEL 5 +ptrdiff_t APP_CC send_channel_data(int, char *, size_t); +ptrdiff_t APP_CC send_channel_data_multiple_atomic(int, unsigned int, char * [], size_t []); +int APP_CC main_cleanup(void); +#define LOG_LEVEL 255 #define LOG(_a, _params) \ { \ if (_a < LOG_LEVEL) \ @@ -28,4 +31,24 @@ } \ } +#define OLDDBGLOG(_itxt) \ +{ \ + int taskq = 0; \ + char taskq_text[256]; \ + if (taskq == 0) \ + { \ + g_file_delete("/tmp/taskq.log"); \ + taskq = g_file_open("/tmp/taskq.log"); \ + } \ + g_snprintf(taskq_text, _itxt, 255 ); \ + g_lfile_writeln(taskq, "---"); \ + g_lfile_write(taskq, taskq_text); \ +} + +unsigned int taskq_count; +void DBGLOG(const char *, const char *); + +tc_t g_chan_mutex; +tc_p mutex_chan; + #endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/clipboard.c posixrdp/posixxrdp.orig/sesman/chansrv/clipboard.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/clipboard.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/clipboard.c 2010-11-08 09:56:45.000000000 +0100 @@ -22,10 +22,12 @@ */ +#include #include #include #include #include "arch.h" +#include "defines.h" #include "parse.h" #include "os_calls.h" #include "chansrv.h" @@ -39,32 +41,32 @@ static Atom g_secondary_atom = 0; static Atom g_get_time_atom = 0; static Atom g_utf8_atom = 0; -static int g_x_socket = 0; +static tbus g_x_socket = 0; static tbus g_x_wait_obj = 0; -static int g_clip_up = 0; +static unsigned char g_clip_up = 0; static Window g_wnd = 0; static Screen* g_screen = 0; static int g_screen_num = 0; -static int g_xfixes_event_base = 0; +static size_t g_xfixes_event_base = 0; -static int g_last_clip_size = 0; +static size_t g_last_clip_size = 0; static char* g_last_clip_data = 0; static Atom g_last_clip_type = 0; -static int g_got_selection = 0; /* boolean */ +static unsigned char g_got_selection = 0; /* boolean */ static Time g_selection_time = 0; -static struct stream* g_ins = 0; +static struct stream * g_ins = 0; static XSelectionRequestEvent g_selection_request_event[16]; -static int g_selection_request_event_count = 0; +static size_t g_selection_request_event_count = 0; static char* g_data_in = 0; -static int g_data_in_size = 0; +static size_t g_data_in_size = 0; static int g_data_in_time = 0; static int g_data_in_up_to_date = 0; -static int g_got_format_announce = 0; -static int g_waiting_for_data_response = 0; +static unsigned char g_got_format_announce = 0; +static unsigned char g_waiting_for_data_response = 0; static int g_waiting_for_data_response_time = 0; static Display* g_display = 0; @@ -75,7 +77,7 @@ int DEFAULT_CC clipboard_error_handler(Display* dis, XErrorEvent* xer) { - char text[256]; + char text[256] = ""; XGetErrorText(dis, xer->error_code, text, 255); LOG(1, ("error [%s]", text)); @@ -101,6 +103,7 @@ { XEvent xevent; + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_get_server_time() called"); /* append nothing */ XChangeProperty(g_display, g_wnd, g_get_time_atom, XA_STRING, 8, PropModeAppend, "", 0); @@ -113,13 +116,14 @@ } /*****************************************************************************/ -/* returns time in miliseconds - this is like g_time2 in os_calls, but not miliseconds since machine was +/* returns time in milliseconds + this is like g_time2 in os_calls, but not milliseconds since machine was up, something else this is a time value similar to what the xserver uses */ static int APP_CC clipboard_get_local_time(void) { + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_get_local_time() called"); return g_time3(); } @@ -128,16 +132,19 @@ int APP_CC clipboard_init(void) { - struct stream* s; - int size; - int rv; - int input_mask; - int dummy; - int ver_maj; - int ver_min; + int rv = 0; + struct stream* s = (struct stream *)NULL; + size_t size = 0; + int input_mask = 0; + int dummy = 0; + int ver_maj = 0; + int ver_min = 0; Status st; - LOG(5, ("xrdp-chansrv: in clipboard_init")); + g_memset(&st,0,sizeof(Status)); + + LOG(5, ("[xrdp-chansrv]->clipboard_init() called")); + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_init() called"); if (g_clip_up) { return 0; @@ -151,7 +158,7 @@ g_display = XOpenDisplay(0); if (g_display == 0) { - LOG(0, ("clipboard_init: XOpenDisplay failed")); + LOG(0, ("[xrdp-chansrv]->clipboard_init(): XOpenDisplay failed")); rv = 1; } if (rv == 0) @@ -162,7 +169,9 @@ LOG(0, ("clipboard_init: XConnectionNumber failed")); rv = 2; } - g_x_wait_obj = g_create_wait_obj_from_socket(g_x_socket, 0); + else { + g_x_wait_obj = g_create_wait_obj_from_socket(g_x_socket, 0); + } } if (rv == 0) { @@ -177,15 +186,15 @@ { if (!XFixesQueryExtension(g_display, &g_xfixes_event_base, &dummy)) { - LOG(0, ("clipboard_init: no xfixes")); + LOG(0, ("[xrdp-chansrv]->clipboard_init(): no xfixes")); rv = 5; } } if (rv == 0) { - LOG(0, ("clipboard_init: g_xfixes_event_base %d", g_xfixes_event_base)); + LOG(0, ("[xrdp-chansrv]->clipboard_init(): g_xfixes_event_base %d", g_xfixes_event_base)); st = XFixesQueryVersion(g_display, &ver_maj, &ver_min); - LOG(0, ("clipboard_init st %d, maj %d min %d", st, ver_maj, ver_min)); + LOG(0, ("[xrdp-chansrv]->clipboard_init(): st = %d; maj = %d; min = %d", st, ver_maj, ver_min)); g_screen_num = DefaultScreen(g_display); g_screen = ScreenOfDisplay(g_display, g_screen_num); g_clip_property_atom = XInternAtom(g_display, "XRDP_CLIP_PROPERTY_ATOM", @@ -212,19 +221,20 @@ if (rv == 0) { make_stream(s); - init_stream(s, 8192); + init_stream(s, MAX_STREAM); out_uint16_le(s, 1); /* CLIPRDR_CONNECT */ out_uint16_le(s, 0); /* status */ out_uint32_le(s, 0); /* length */ out_uint32_le(s, 0); /* extra 4 bytes ? */ s_mark_end(s); size = (int)(s->end - s->data); - LOG(5, ("clipboard_init: data out, sending " + LOG(5, ("[xrdp-chansrv]->clipboard_init(): data out, sending " "CLIPRDR_CONNECT (clip_msg_id = 1)")); rv = send_channel_data(g_cliprdr_chan_id, s->data, size); + LOG(5,("[xrdp-chansrv]->clipboard_init(): g_cliprdr_chan_id = %d",g_cliprdr_chan_id)); if (rv != 0) { - LOG(0, ("clipboard_init: send_channel_data failed " + LOG(0, ("[xrdp-chansrv]->clipboard_init(): send_channel_data failed " "rv = %d", rv)); rv = 4; } @@ -234,7 +244,7 @@ { g_clip_up = 1; make_stream(g_ins); - init_stream(g_ins, 8192) + init_stream(g_ins, MAX_STREAM) } else { @@ -258,14 +268,16 @@ g_wnd = 0; } g_x_socket = 0; - g_free(g_last_clip_data); + //g_free(g_last_clip_data); g_last_clip_data = 0; g_last_clip_size = 0; - free_stream(g_ins); + if (g_ins != 0) { + //free_stream(g_ins); + } g_ins = 0; if (g_display != 0) { - XCloseDisplay(g_display); + //XCloseDisplay(g_display); g_display = 0; } g_clip_up = 0; @@ -276,10 +288,10 @@ static int APP_CC clipboard_send_data_request(void) { - struct stream* s; - int size; - int rv; - int num_chars; + int rv = 0; + struct stream * s = (struct stream *)NULL; + ptrdiff_t size = 0; + size_t num_chars = 0; LOG(5, ("clipboard_send_data_request:")); if (!g_got_format_announce) @@ -289,13 +301,13 @@ } g_got_format_announce = 0; make_stream(s); - init_stream(s, 8192); + init_stream(s, MAX_STREAM); out_uint16_le(s, 4); /* CLIPRDR_DATA_REQUEST */ out_uint16_le(s, 0); /* status */ out_uint32_le(s, 4); /* length */ out_uint32_le(s, 0x0d); s_mark_end(s); - size = (int)(s->end - s->data); + size = s->end - s->data; LOG(5, ("clipboard_send_data_request: data out, sending " "CLIPRDR_DATA_REQUEST (clip_msg_id = 4)")); rv = send_channel_data(g_cliprdr_chan_id, s->data, size); @@ -307,18 +319,18 @@ static int APP_CC clipboard_send_format_ack(void) { - struct stream* s; - int size; - int rv; + struct stream* s = (struct stream *)NULL; + ptrdiff_t size = 0; + int rv = 0; make_stream(s); - init_stream(s, 8192); + init_stream(s, MAX_STREAM); out_uint16_le(s, 3); /* CLIPRDR_FORMAT_ACK */ out_uint16_le(s, 1); /* status */ out_uint32_le(s, 0); /* length */ out_uint32_le(s, 0); /* extra 4 bytes ? */ s_mark_end(s); - size = (int)(s->end - s->data); + size = s->end - s->data; LOG(5, ("clipboard_send_format_ack: data out, sending " "CLIPRDR_FORMAT_ACK (clip_msg_id = 3)")); rv = send_channel_data(g_cliprdr_chan_id, s->data, size); @@ -330,19 +342,19 @@ static int APP_CC clipboard_send_format_announce(void) { - struct stream* s; - int size; - int rv; + struct stream* s = (struct stream *)NULL; + ptrdiff_t size = 0; + int rv = 0; make_stream(s); - init_stream(s, 8192); + init_stream(s, MAX_STREAM); out_uint16_le(s, 2); /* CLIPRDR_FORMAT_ANNOUNCE */ out_uint16_le(s, 0); /* status */ out_uint32_le(s, 0x90); /* length */ out_uint32_le(s, 0x0d); /* extra 4 bytes ? */ out_uint8s(s, 0x90); s_mark_end(s); - size = (int)(s->end - s->data); + size = s->end - s->data; LOG(5, ("clipboard_send_format_announce: data out, sending " "CLIPRDR_FORMAT_ANNOUNCE (clip_msg_id = 2)")); rv = send_channel_data(g_cliprdr_chan_id, s->data, size); @@ -353,12 +365,13 @@ /*****************************************************************************/ /* returns number of bytes written */ static int APP_CC -clipboard_out_unicode(struct stream* s, char* text, int num_chars) +clipboard_out_unicode(struct stream * s, char * text, size_t num_chars) { - int index; - int lnum_chars; - twchar* ltext; + ptrdiff_t index = 0; + size_t lnum_chars = 0; + twchar * ltext = (twchar *)NULL; + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_out_unicode() called"); if ((num_chars < 1) || (text == 0)) { return 0; @@ -376,7 +389,7 @@ out_uint16_le(s, ltext[index]); index++; } - g_free(ltext); + //g_free(ltext); return index * 2; } @@ -384,12 +397,13 @@ static int APP_CC clipboard_send_data_response(void) { - struct stream* s; - int size; - int rv; - int num_chars; + int rv = 0; + struct stream* s = (struct stream *)NULL; + ptrdiff_t size = 0; + size_t num_chars = 0; LOG(10, ("clipboard_send_data_response:")); + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_send_data_response() called"); num_chars = 0; if (g_last_clip_data != 0) { @@ -399,6 +413,7 @@ if (num_chars < 0) { LOG(0, ("clipboard_send_data_response: bad string")); + //DBGLOG("clipboard","clipboard_send_data_response: bad string"); num_chars = 0; } } @@ -414,11 +429,12 @@ { LOG(0, ("clipboard_send_data_response: error " "clipboard_out_unicode didn't write right number of bytes")); + //DBGLOG("clipboard","clipboard_send_data_response: error (clipboard_out_unicode didn't write right number of bytes)"); } out_uint16_le(s, 0); /* nil for string */ out_uint32_le(s, 0); s_mark_end(s); - size = (int)(s->end - s->data); + size = s->end - s->data; LOG(5, ("clipboard_send_data_response: data out, sending " "CLIPRDR_DATA_RESPONSE (clip_msg_id = 5) size %d num_chars %d", size, num_chars)); @@ -433,6 +449,9 @@ { Window owner; + g_memset(&owner,0,sizeof(Window)); + + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_set_selection_owner() called"); g_selection_time = clipboard_get_server_time(); XSetSelectionOwner(g_display, g_clipboard_atom, g_wnd, g_selection_time); owner = XGetSelectionOwner(g_display, g_clipboard_atom); @@ -447,11 +466,12 @@ /*****************************************************************************/ static int APP_CC -clipboard_provide_selection(XSelectionRequestEvent* req, Atom type, int format, - char* data, int length) +clipboard_provide_selection(XSelectionRequestEvent * req, Atom type, int format, + char * data, size_t length) { XEvent xev; + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_provide_selection() called"); XChangeProperty(g_display, req->requestor, req->property, type, format, PropModeReplace, (tui8*)data, length); g_memset(&xev, 0, sizeof(xev)); @@ -473,6 +493,7 @@ { XEvent xev; + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_refuse_selection() called"); g_memset(&xev, 0, sizeof(xev)); xev.xselection.type = SelectionNotify; xev.xselection.send_event = True; @@ -489,11 +510,14 @@ /*****************************************************************************/ static int APP_CC clipboard_process_format_announce(struct stream* s, int clip_msg_status, - int clip_msg_len) + size_t clip_msg_len) { Window owner; + g_memset(&owner,0,sizeof(Window)); + LOG(5, ("clipboard_process_format_announce: CLIPRDR_FORMAT_ANNOUNCE")); + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_process_format_announce(): CLIPRDR_FORMAT_ANNOUNCE"); //g_hexdump(s->p, s->end - s->p); clipboard_send_format_ack(); g_got_format_announce = 1; @@ -501,16 +525,18 @@ if (clipboard_set_selection_owner() != 0) { LOG(0, ("clipboard_process_format_announce: XSetSelectionOwner failed")); + //DBGLOG("clipboard","clipboard_process_format_announce: XSetSelectionOwner failed"); } return 0; } /*****************************************************************************/ static int APP_CC -clipboard_prcoess_format_ack(struct stream* s, int clip_msg_status, - int clip_msg_len) +clipboard_process_format_ack(struct stream* s, int clip_msg_status, + size_t clip_msg_len) { - LOG(5, ("clipboard_prcoess_format_ack: CLIPRDR_FORMAT_ACK")); + LOG(5, ("clipboard_process_format_ack: CLIPRDR_FORMAT_ACK")); + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_process_format_ack(): CLIPRDR_FORMAT_ACK"); //g_hexdump(s->p, s->end - s->p); return 0; } @@ -518,9 +544,10 @@ /*****************************************************************************/ static int APP_CC clipboard_process_data_request(struct stream* s, int clip_msg_status, - int clip_msg_len) + size_t clip_msg_len) { LOG(5, ("clipboard_process_data_request: CLIPRDR_DATA_REQUEST")); + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_process_data_request(): CLIPRDR_DATA_REQUEST"); //g_hexdump(s->p, s->end - s->p); clipboard_send_data_response(); return 0; @@ -529,20 +556,24 @@ /*****************************************************************************/ static int APP_CC clipboard_process_data_response(struct stream* s, int clip_msg_status, - int clip_msg_len) + size_t clip_msg_len) { XEvent xev; - XSelectionRequestEvent* lxev; - twchar* wtext; + XSelectionRequestEvent * lxev = (XSelectionRequestEvent *)NULL; + twchar * wtext = (twchar *)NULL; twchar wchr; - int len; - int index; - int wtext_size; - int data_in_len; + ptrdiff_t len = 0; + ptrdiff_t index = 0; + ptrdiff_t wtext_size = 0; + ptrdiff_t data_in_len = 0; + + g_memset(&xev,0,sizeof(XEvent)); + g_memset(&wchr,0,sizeof(twchar)); LOG(5, ("clipboard_process_data_response: CLIPRDR_DATA_RESPONSE")); + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_process_data_response(): CLIPRDR_DATA_RESPONSE"); g_waiting_for_data_response = 0; - len = (int)(s->end - s->p); + len = s->end - s->p; if (len < 1) { return 0; @@ -565,7 +596,7 @@ index++; } wtext[index] = 0; - g_free(g_data_in); + //g_free(g_data_in); g_data_in = 0; g_data_in_size = 0; g_data_in_time = 0; @@ -575,11 +606,12 @@ g_data_in = (char*)g_malloc(len + 16, 0); if (g_data_in == 0) { - g_free(wtext); + //g_free(wtext); return 0; } g_data_in_size = len; g_wcstombs(g_data_in, wtext, len + 1); + len = g_strlen(g_data_in); g_data_in_time = clipboard_get_local_time(); g_data_in_up_to_date = 1; } @@ -596,21 +628,22 @@ } } g_selection_request_event_count = 0; - g_free(wtext); + //g_free(wtext); return 0; } /*****************************************************************************/ int APP_CC -clipboard_data_in(struct stream* s, int chan_id, int chan_flags, int length, - int total_length) +clipboard_data_in(struct stream* s, int chan_id, int chan_flags, size_t length, + size_t total_length) { - int clip_msg_id; - int clip_msg_len; - int clip_msg_status; - int rv; - struct stream* ls; + int rv = 0; + int clip_msg_id = 0; + ptrdiff_t clip_msg_len = 0; + int clip_msg_status = 0; + struct stream * ls = (struct stream *)NULL; + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_data_in() called"); LOG(10, ("clipboard_data_in: chan_is %d " "chan_flags %d length %d total_length %d", chan_id, chan_flags, length, total_length)); @@ -646,7 +679,7 @@ clip_msg_len); break; case 3: /* CLIPRDR_FORMAT_ACK */ - rv = clipboard_prcoess_format_ack(ls, clip_msg_status, + rv = clipboard_process_format_ack(ls, clip_msg_status, clip_msg_len); break; case 4: /* CLIPRDR_DATA_REQUEST */ @@ -680,11 +713,13 @@ Time timestamp; Time selection_timestamp; } XFixesSelectionNotifyEvent; */ + static int APP_CC clipboard_event_selection_owner_notify(XEvent* xevent) { - XFixesSelectionNotifyEvent* lxevent; + XFixesSelectionNotifyEvent * lxevent = (XFixesSelectionNotifyEvent *)NULL; + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_event_selection_owner_notify() called"); lxevent = (XFixesSelectionNotifyEvent*)xevent; LOG(5, ("clipboard_event_selection_owner_notify: " "window %d subtype %d owner %d g_wnd %d", @@ -692,7 +727,7 @@ if (lxevent->owner == g_wnd) { LOG(5, ("clipboard_event_selection_owner_notify: skipping, " - "onwer == g_wnd")); + "owner == g_wnd")); g_got_selection = 1; return 0; } @@ -706,16 +741,19 @@ /* returns error get a window property from wnd */ static int APP_CC -clipboard_get_window_property(Window wnd, Atom prop, Atom* type, int* fmt, - int* n_items, char** xdata, int* xdata_size) +clipboard_get_window_property(Window wnd, Atom prop, Atom* type, int * fmt, + size_t * n_items, char** xdata, size_t * xdata_size) { - int lfmt; - int lxdata_size; - unsigned long ln_items; - unsigned long llen_after; - tui8* lxdata; + int lfmt = 0; + size_t lxdata_size = 0; + unsigned long int ln_items = 0; + unsigned long int llen_after = 0; + tui8 * lxdata = (tui8 *)NULL; Atom ltype; + g_memset(<ype,0,sizeof(Atom)); + + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_get_window_property() called"); lxdata = 0; ltype = 0; XGetWindowProperty(g_display, g_wnd, prop, 0, 0, 0, @@ -725,11 +763,13 @@ if (ltype == 0) { /* XGetWindowProperty failed */ + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_get_window_property(): XGetWindowProperty() failed"); return 1; } if (llen_after < 1) { /* no data, ok */ + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_get_window_property(): no data, OK"); return 0; } lxdata = 0; @@ -740,6 +780,7 @@ if (ltype == 0) { /* XGetWindowProperty failed */ + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_get_window_property(): XGetWindowProperty() failed"); XFree(lxdata); return 1; } @@ -747,12 +788,14 @@ if (lxdata_size < 1) { /* should not happen */ + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_get_window_property(): lxdata_size < 1!"); XFree(lxdata); return 2; } if (llen_after > 0) { /* should not happen */ + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_get_window_property(): ilen_after > 0!"); XFree(lxdata); return 3; } @@ -778,6 +821,7 @@ { *type = ltype; } + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_get_window_property() done."); return 0; } @@ -795,23 +839,35 @@ Atom property; // atom or None Time time; } XSelectionEvent; */ + static int APP_CC clipboard_event_selection_notify(XEvent* xevent) { - XSelectionEvent* lxevent; - char* data; - int data_size; - int n_items; - int fmt; - int rv; - int index; - int convert_to_string; - int convert_to_utf8; - int send_format_announce; - int atom; - int* atoms; + XSelectionEvent * lxevent = (XSelectionEvent *)NULL; + char * data = (char *)NULL; + size_t data_size = 0; + size_t n_items = 0; + int fmt = 0; + int rv = 0; + ptrdiff_t index = 0; + unsigned char convert_to_string = 0; + unsigned char convert_to_utf8 = 0; + unsigned char send_format_announce = 0; + int atom = 0; + int * atoms = (int *)NULL; + //Atom *atoms; Atom type; + char tbuf[256] = ""; + char tbuf2[256] = ""; + char * tbuf3 = (char *)NULL; + Status st; + g_memset(&type,0,sizeof(Atom)); + g_memset(&st,0,sizeof(Status)); + g_memset(tbuf,0,sizeof(char) * 256); + g_memset(tbuf2,0,sizeof(char) * 256); + + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_event_selection_notify() called"); LOG(5, ("clipboard_event_selection_notify:")); convert_to_string = 0; convert_to_utf8 = 0; @@ -824,6 +880,7 @@ { LOG(0, ("clipboard_event_selection_notify: clip could " "not be converted")); + MDBGLOG("clipboard","INFO\t[%s()]: clip could not be converted",__func__); rv = 1; } if (rv == 0) @@ -835,6 +892,7 @@ { LOG(0, ("clipboard_event_selection_notify: " "clipboard_get_window_property failed error %d", rv)); + MDBGLOG("clipboard","ERROR\t[%s()]: clipboard_get_window_property() failed (error %d)", __func__, rv); } XDeleteProperty(g_display, lxevent->requestor, lxevent->property); } @@ -846,12 +904,17 @@ { if ((type == XA_ATOM) && (fmt == 32)) { - atoms = (int*)data; + atoms = (int *)data; for (index = 0; index < n_items; index++) { - atom = atoms[index]; - LOG(5, ("clipboard_event_selection_notify: %d %s %d", atom, - XGetAtomName(g_display, atom), XA_STRING)); + atom = atoms[index]; + if (atom!=0) { + //LOG(5, ("clipboard_event_selection_notify: %d %s %d", atom, + // XGetAtomName(g_display, atom), XA_STRING)); + //snprintf(tbuf,255," (%d of %d) [xrdp-chansrv]->clipboard_event_selection_notify(): %d %s\0", index, n_items, atom, XGetAtomName(g_display, atom)); + //tbuf3 = XGetAtomName(g_display, atom); + //snprintf(tbuf,255," (%d of %d) [xrdp-chansrv]->clipboard_event_selection_notify(): %d %s\0", index, n_items, atom, tbuf3); + ////DBGLOG("clipboard",tbuf); if (atom == g_utf8_atom) { convert_to_utf8 = 1; @@ -860,6 +923,7 @@ { convert_to_string = 1; } + } } } else @@ -873,7 +937,8 @@ { LOG(5, ("clipboard_event_selection_notify: UTF8_STRING data_size %d", data_size)); - g_free(g_last_clip_data); + MDBGLOG("clipboard","ERROR\t[%s()]: UTF8_STRING data_size = %d",__func__,data_size); + //g_free(g_last_clip_data); g_last_clip_size = data_size; g_last_clip_data = g_malloc(g_last_clip_size + 1, 0); g_last_clip_type = g_utf8_atom; @@ -885,7 +950,9 @@ { LOG(5, ("clipboard_event_selection_notify: XA_STRING data_size %d", data_size)); - g_free(g_last_clip_data); + //snprintf(tbuf,255,"[xrdp-chansrv]->clipboard_event_selection_notify(): XA_STRING data_size = %d",data_size); + //DBGLOG("clipboard",tbuf); + //g_free(g_last_clip_data); g_last_clip_size = data_size; g_last_clip_data = g_malloc(g_last_clip_size + 1, 0); g_last_clip_type = XA_STRING; @@ -896,20 +963,24 @@ else { LOG(0, ("clipboard_event_selection_notify: unknown target")); + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_event_selection_notify(): unknown target"); } } else { LOG(0, ("clipboard_event_selection_notify: unknown selection")); + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_event_selection_notify(): unknown selection"); } } if (convert_to_utf8) { + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_event_selection_notify(): convert_to_utf8"); XConvertSelection(g_display, g_clipboard_atom, g_utf8_atom, g_clip_property_atom, g_wnd, lxevent->time); } else if (convert_to_string) { + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_event_selection_notify(): convert_to_string"); XConvertSelection(g_display, g_clipboard_atom, XA_STRING, g_clip_property_atom, g_wnd, lxevent->time); } @@ -920,7 +991,7 @@ rv = 4; } } - g_free(data); + //g_free(data); return rv; } @@ -939,18 +1010,25 @@ Atom property; Time time; } XSelectionRequestEvent; */ + static int APP_CC clipboard_event_selection_request(XEvent* xevent) { XEvent xev; - XSelectionRequestEvent* lxev; - tui32 ui32[8]; + XSelectionRequestEvent* lxev = (XSelectionRequestEvent *)NULL; + tui32 ui32[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; Atom type; - int fmt; - int n_items; - int xdata_size; - char* xdata; + int fmt = 0; + size_t n_items = 0; + size_t xdata_size = 0; + char* xdata = (char *)NULL; + char tbuf[256] = ""; + + g_memset(tbuf,0,sizeof(char) * 256); + g_memset(&type,0,sizeof(Atom)); + g_memset(&xev,0,sizeof(XEvent)); + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_event_selection_request() called"); lxev = (XSelectionRequestEvent*)xevent; LOG(5, ("clipboard_event_selection_request: g_wnd %d, " ".requestor %d .owner %d .selection %d '%s' .target %d .property %d", @@ -960,11 +1038,13 @@ if (lxev->property == None) { LOG(5, ("clipboard_event_selection_request: lxev->property is None")); + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_event_selection_request(): lxev->property is None"); } else if (lxev->target == g_targets_atom) { /* requestor is asking what the selection can be converted to */ LOG(5, ("clipboard_event_selection_request: g_targets_atom")); + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_event_selection_request(): g_targets_atom"); ui32[0] = g_targets_atom; ui32[1] = g_timestamp_atom; ui32[2] = g_multiple_atom; @@ -976,23 +1056,25 @@ { /* requestor is asking the time I got the selection */ LOG(5, ("clipboard_event_selection_request: g_timestamp_atom")); + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_event_selection_request(): g_timestamp_atom"); ui32[0] = g_selection_time; return clipboard_provide_selection(lxev, XA_INTEGER, 32, (char*)ui32, 1); } else if (lxev->target == g_multiple_atom) { /* target, property pairs */ - LOG(5, ("clipboard_event_selection_request: g_multiple_atom")); - if (clipboard_get_window_property(xev.xselection.requestor, - xev.xselection.property, - &type, &fmt, &n_items, &xdata, - &xdata_size) == 0) - { - LOG(5, ("clipboard_event_selection_request: g_multiple_atom " - "n_items %d", n_items)); - /* todo */ - g_free(xdata); - } + LOG(5, ("[xrdp-chansrv]->clipboard_event_selection_request(): g_multiple_atom")); + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_event_selection_request(): g_multiple_atom"); +// if (clipboard_get_window_property(xev.xselection.requestor, +// xev.xselection.property, +// &type, &fmt, &n_items, &xdata, +// &xdata_size) == 0) +// { +// LOG(5, ("clipboard_event_selection_request: g_multiple_atom " +// "n_items %d", n_items)); +// /* todo */ +// //g_free(xdata); +// } } else if ((lxev->target == XA_STRING) || (lxev->target == g_utf8_atom)) { @@ -1006,6 +1088,7 @@ if (g_selection_request_event_count > 10) { LOG(0, ("clipboard_event_selection_request: error, too many requests")); + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_event_selection_request(): error, too many requests"); } else { @@ -1025,6 +1108,8 @@ { LOG(0, ("clipboard_event_selection_request: unknown " "target %s", XGetAtomName(g_display, lxev->target))); + snprintf(tbuf,255,"[xrdp-chansrv]->clipboard_event_selection_request(): unknown target (%s)\0", XGetAtomName(g_display, lxev->target)); + //DBGLOG("clipboard",tbuf); } clipboard_refuse_selection(lxev); return 0; @@ -1042,9 +1127,11 @@ Atom selection; Time time; } XSelectionClearEvent; */ + static int APP_CC clipboard_event_selection_clear(XEvent* xevent) { + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_event_selection_clear() called"); LOG(5, ("clipboard_event_selection_clear:")); return 0; } @@ -1061,9 +1148,11 @@ Time time; int state; // PropertyNewValue or PropertyDelete } XPropertyEvent; */ + static int APP_CC clipboard_event_property_notify(XEvent* xevent) { + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_event_property_notify() called"); LOG(10, ("clipboard_check_wait_objs: PropertyNotify .window %d " ".state %d .atom %d", xevent->xproperty.window, xevent->xproperty.state, xevent->xproperty.atom)); @@ -1075,10 +1164,11 @@ this is called to get any wait objects for the main loop timeout can be nil */ int APP_CC -clipboard_get_wait_objs(tbus* objs, int* count, int* timeout) +clipboard_get_wait_objs(tbus* objs, ptrdiff_t * count, int * timeout) { - int lcount; + ptrdiff_t lcount = 0; + ////DBGLOG("clipboard","[xrdp-chansrv]->clipboard_get_wait_objs() called"); if ((!g_clip_up) || (objs == 0) || (count == 0)) { return 0; @@ -1095,8 +1185,9 @@ clipboard_check_wait_objs(void) { XEvent xevent; - int time_diff; + int time_diff = 0; + ////DBGLOG("clipboard","[xrdp-chansrv]->clipboard_check_wait_objs() called"); if (!g_clip_up) { return 0; @@ -1107,6 +1198,7 @@ { /* something is wrong, should not get here */ LOG(0, ("clipboard_check_wait_objs: sck closed")); + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_check_wait_objs(): sck closed"); return 0; } if (g_waiting_for_data_response) @@ -1117,6 +1209,7 @@ { LOG(0, ("clipboard_check_wait_objs: warning, waiting for " "data response too long")); + //DBGLOG("clipboard","[xrdp-chansrv]->clipboard_check_wait_objs(): warning, waiting for data response too long"); } } while (XPending(g_display) > 0) @@ -1147,6 +1240,7 @@ } LOG(0, ("clipboard_check_wait_objs unknown type %d", xevent.type)); + //MDBGLOG("clip","[xrdp-chansrv]->clipboard_check_wait_objs(): unknown type (%d)",xevent.type); break; } } diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/clipboard.h posixrdp/posixxrdp.orig/sesman/chansrv/clipboard.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/clipboard.h 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/clipboard.h 2010-11-08 09:56:45.000000000 +0100 @@ -2,18 +2,31 @@ #if !defined(CLIPBOARD_H) #define CLIPBOARD_H +#include +#include + #include "arch.h" #include "parse.h" +#ifndef BYTE +#define BYTE uint8_t +#endif +#ifndef WORD +#define WORD uint16_t +#endif +#ifndef DWORD +#define DWORD uint32_t +#endif + int APP_CC clipboard_init(void); int APP_CC clipboard_deinit(void); int APP_CC -clipboard_data_in(struct stream* s, int chan_id, int chan_flags, int length, - int total_length); +clipboard_data_in(struct stream* s, int chan_id, int chan_flags, size_t length, + size_t total_length); int APP_CC -clipboard_get_wait_objs(tbus* objs, int* count, int* timeout); +clipboard_get_wait_objs(tbus* objs, ptrdiff_t * count, int* timeout); int APP_CC clipboard_check_wait_objs(void); diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/devredir.c posixrdp/posixxrdp.orig/sesman/chansrv/devredir.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/devredir.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/devredir.c 2010-11-08 09:56:45.000000000 +0100 @@ -17,44 +17,4465 @@ Copyright (C) Jay Sorg 2009 */ +#include +#include +#include +#include +#include + #include "arch.h" -#include "parse.h" +#include "chansrv.h" +#include "defines.h" +#include "devredir_defs.h" +#include "devredir.h" #include "os_calls.h" +#include "parse.h" +#include "rdpdr.h" +#include "rdpdr_methods.h" +#include "trans.h" +#include "thread_calls.h" +#include "thread_macros.h" + +#include "dbg.h" + +#if defined(MDBGLOG) +//#undef MDBGLOG +//#define MDBGLOG(...) ; +#endif + +#ifndef MAX_PENDING +#define MAX_PENDING 512 +#endif + +#ifndef WO_PATH +#define WO_PATH "/tmp/xrdp_chansrv_%8.8x_rdpdr" +#endif + +#ifndef FSBASE_PATH +#define FSBASE_PATH "/media/tsclient" +#endif + +extern tc_t g_out_mutex; +extern tc_p mutex_out; +tc_p mutex_client_devicelist = (tc_p)NULL; +static tc_t g_client_devicelist_mutex; +static tc_t g_fs_arr_mutex; +static tc_t g_port_arr_mutex; +static tc_t g_printer_arr_mutex; +static tc_t g_smartcard_arr_mutex; +static tc_p mutex_fs_arr = (tc_p)NULL; +static tc_p mutex_port_arr = (tc_p)NULL; +static tc_p mutex_printer_arr = (tc_p)NULL; +static tc_p mutex_smartcard_arr = (tc_p)NULL; + +static tc_t g_cb_mutex; +static tc_p mutex_cb = (tc_p)NULL; + +DR_DEVICELIST_ANNOUNCE * g_client_devicelist = NULL; +static char g_fbase[1024] = FSBASE_PATH; + +static unsigned char g_is_child = 0; +static int g_idx = 0; +static int g_handle_filesystem_called = 0; +static tc_t g_handle_filesystem_mutex; +static tc_p g_handle_fs_mut = (tc_p)NULL; + +static int g_rdpdr_up = 0; +static tbus g_rdpdr_wait_obj = -1; +static unsigned int g_received_close_pdu = 0; +static struct stream * g_ins = (struct stream *)NULL; +static int g_client_announce_reply_received = 0; +static int g_client_name_request_received = 0; +static int g_user_loggedon_sent = 0; +static int g_core_capabilities_requested = 0; +static int g_client_id = 0x0001; +static char * g_client_computer_name = (char *)NULL; +static int g_child_pid = 0; +static int l_child_pid = 0; +static int p_child_pid = 0; +static int s_child_pid = 0; +static rdpfs ** g_fs_arr = (rdpfs **)NULL; +static rdpport_t ** g_port_arr = (rdpport_t **)NULL; +static rdpprint ** g_printer_arr = (rdpprint **)NULL; +static rdpsc ** g_smartcard_arr = (rdpsc **)NULL; + +int g_fs_count = 0; +int g_port_count = 0; +int g_printer_count = 0; +int g_smartcard_count = 0; + +static int g_opid = 5; +static callback g_callbacks[MAX_PENDING]; +static int g_file_id = -1; + +static int g_pending_operations[MAX_PENDING]; + +static int APP_CC rdpdr_process_format_announce(struct stream *, int, int); +static int APP_CC rdpdr_process_format_ack(struct stream *, int, int); +static int APP_CC rdpdr_process_data_request(struct stream *, int, int); +static int APP_CC rdpdr_process_data_response(struct stream *, int, int); +static int APP_CC rdpdr_process_DEVICELIST_ANNOUNCE(struct stream *); + +static char * APP_CC ucs2ascii(const uint8_t *); + +static int APP_CC rdpdr_child_loop(int); +static int APP_CC get_opid(void *); +static int APP_CC register_opid(void *, int); +static int APP_CC strike_opid(void *, int); +static int APP_CC opid_is_registered(void *, int); +static int APP_CC cb_set_data(struct _callback *, int, const BYTE *); +static int APP_CC cb_set_func(struct _callback *, void (*)(struct _rdpfs *, int, tbus, struct trans *, DWORD, DWORD, int, BYTE *)); +static void * APP_CC cb_call(void *); +static int APP_CC cb_call_data(struct _callback *, int, const BYTE *); +static int APP_CC get_opcode_from_opid(int); +static callback * APP_CC get_callback_from_opid(int); +static void APP_CC cb_send_buf(struct _rdpfs *, int, tbus, struct trans *, DWORD, DWORD, int, BYTE *); +static void APP_CC cb_send_bare(struct _rdpfs *, int, tbus, struct trans *, DWORD, DWORD, int, BYTE *); +static inline int APP_CC is_filesystem(int); +static inline int APP_CC is_port(int); +static inline int APP_CC is_serial(int); +static inline int APP_CC is_parallel(int); +static inline int APP_CC is_printer(int); +static inline int APP_CC is_smartcard(int); +static int APP_CC get_device_index(int); + +static int APP_CC rdpdr_process_DEVICE_REPLY(struct stream *); +static int APP_CC rdpdr_process_DEVICE_IOREQUEST(struct stream *); +static int APP_CC rdpdr_process_DEVICE_IOCOMPLETION(struct stream *); +static int APP_CC rdpdr_process_SERVER_CAPABILITY(struct stream *); +static int APP_CC rdpdr_process_CLIENT_CAPABILITY(struct stream *); +static int APP_CC rdpdr_process_DEVICELIST_REMOVE(struct stream *); + +char * APP_CC ntstatus_string(uint32_t); +static int APP_CC filesystem_data_in(struct trans *); +static int APP_CC port_data_in(struct trans *); +static int APP_CC printer_data_in(struct trans *); +static int APP_CC smartcard_data_in(struct trans *); + +static void test_serial_port(int); + + +static tc_t g_getattr_mutex; +static tc_p mutex_getattr = (tc_p)NULL; +struct getattr_queue; +typedef struct getattr_queue { + struct getattr_queue * next; + struct getattr_queue * prev; + int device_id; + int basic_done; + int fhandle; + int uniqid; + int opid; + int opcode; + tc_t lock; + DR_DRIVE_QUERY_INFORMATION_RSP rsp; +} getattr_queue_t, * getattr_queue_p; +static getattr_queue_t * g_getattr_q = (getattr_queue_t *)NULL; + +#define GETATTR_CREATE() (getattr_queue_t *)g_malloc(sizeof(getattr_queue_t), 1) +#define GETATTR_INIT(x) { \ + if (x != NULL) { \ + tc_t l_tattr; \ + tc_p p_tattr = (tc_p)(&l_tattr); \ + g_memset((void *)(&l_tattr),0,sizeof(tc_t)); \ + TC_MUTATTR_INIT((tc_p)p_tattr); \ + TC_MUTEX_INIT((tc_p)(&(x->lock)), (tc_p)p_tattr); \ + } \ +} +#define DECLARE_GETATTR(inx) \ + getattr_queue_t * inx = (getattr_queue_t *)NULL; \ + { \ + inx = GETATTR_CREATE(); \ + if (inx != NULL) { \ + GETATTR_INIT(inx); \ + } \ + } +#define GETATTR_ENQ(x) { \ + if (g_getattr_q == NULL) { \ + g_getattr_q = x; \ + if (g_getattr_q != NULL) { \ + g_getattr_q->prev = NULL; \ + g_getattr_q->next = NULL; \ + } \ + } \ + else { \ + getattr_queue_t * tlmp = (getattr_queue_t *)NULL; \ + tlmp = g_getattr_q; \ + while (tlmp != NULL && tlmp->next != NULL) { \ + tlmp = tlmp->next; \ + } \ + tlmp->next = x; \ + if (x != NULL) { \ + x->prev = tlmp; \ + x->next = NULL; \ + } \ + } \ +} +#define GETATTR_DEQ(x) { \ + if (x != NULL) { \ + (*(x)) = g_getattr_q; \ + (*(x))->prev = NULL; \ + (*(x))->next = NULL; \ + } \ + if (g_getattr_q != NULL) { \ + g_getattr_q = g_getattr_q->next; \ + g_getattr_q->prev = NULL; \ + } \ +} +#define GETATTR_FIND(x, y, z) { \ + if (g_getattr_q == NULL) { \ + z = NULL; \ + } \ + else { \ + int tdone = 0; \ + getattr_queue_t * tlmp = (getattr_queue_t *)NULL; \ + z = tlmp; \ + tlmp = g_getattr_q; \ + if (tlmp != NULL && tlmp->device_id == x && tlmp->opid == y) { \ + z = tlmp; \ + tdone = 1; \ + } \ + while (tlmp != NULL && tdone < 1) { \ + if (tlmp->device_id == x && tlmp->opid == y) { \ + z = tlmp; \ + tdone = 1; \ + } \ + else { \ + tlmp = tlmp->next; \ + } \ + } \ + } \ +} +#define GETATTR_CUT(x) { \ + if (x != NULL) { \ + if (x->prev == NULL) { \ + g_getattr_q = g_getattr_q->next; \ + if (g_getattr_q != NULL) { \ + g_getattr_q->prev = NULL; \ + } \ + } \ + else if (x->prev != NULL) { \ + x->prev->next = x->next; \ + if (x->next != NULL) { \ + x->next->prev = x->prev; \ + } \ + } \ + } \ +} + +static int g_no_more_files = 0; +static struct stream * g_u = (struct stream *)NULL; + +tc_mut_t g_mutex; +tc_p mut = (tc_p)NULL; + +extern int g_rdpdr_chan_id; /* in chansrv.c */ +extern rdpfs * rdpfs_main(int, char **, char *); /* in rdpfs.c */ +extern int handle_filesystem(tbus, rdpfs *, rdpfs **, tc_p); /* in rdpfs.c */ +extern rdpport_t * rdpport_main(int, int); /* in rdpport.c */ +extern int handle_port(tbus, rdpport_t *); /* in rdpport.c */ +extern void * rdpuart_addport(void *); /* " */ +extern rdpprint * rdpprint_main(void); /* in rdpprint.c */ +extern int handle_printer(tbus, rdpprint *); /* in rdpprint.c */ +extern rdpsc * rdpsc_main(void); /* in rdpsc.c */ +extern int handle_smartcard(tbus, rdpsc *); /* in rdpsc.c */ -extern int g_rdpdr_chan_id; /* in chansrv.c */ /*****************************************************************************/ int APP_CC -dev_redir_init(void) -{ - return 0; +rdpdr_init(void) { + struct stream * s = (struct stream *)NULL; + int size = 0; + int rv = 0; + int pid = 0; + int input_mask = 0; + int dummy = 0; + int ver_maj = 0; + int ver_min = 0; + char wo_fpath[512]; + void * pdu = (void *)NULL; + + MDBGLOG("redir","INFO\t[%s()]: called [%d, %d]",__func__,g_getpid(),g_gettid()); + + mut = (tc_p)&g_mutex; + tc_mutex_init(mut,NULL); + + g_no_more_files = 0; + make_stream(g_u); + init_stream(g_u, MAX_STREAM); + + { + tc_t mattr; + tc_p pattr = &mattr; + tc_t nattr; + tc_p pnattr = &nattr; + TC_MUTATTR_INIT(pattr); + TC_MUTATTR_SETTYPE(pattr, TC_MUTEX_ERRORCHECK); + TC_MUTATTR_SETPSHARED(pattr, TC_PROCESS_SHARED); + TC_MUTATTR_INIT(pnattr); + TC_MUTATTR_SETTYPE(pnattr, TC_MUTEX_ERRORCHECK); + TC_MUTATTR_SETPSHARED(pattr, TC_PROCESS_PRIVATE); + g_handle_fs_mut = &g_handle_filesystem_mutex; + TC_MUTEX_INIT(g_handle_fs_mut,pnattr); + mutex_client_devicelist = &g_client_devicelist_mutex; + TC_MUTEX_INIT(mutex_client_devicelist, pnattr); + mutex_fs_arr = &g_fs_arr_mutex; + TC_MUTEX_INIT(mutex_fs_arr, pnattr); + mutex_port_arr = &g_port_arr_mutex; + TC_MUTEX_INIT(mutex_port_arr, pnattr); + mutex_printer_arr = &g_printer_arr_mutex; + TC_MUTEX_INIT(mutex_printer_arr, pnattr); + mutex_smartcard_arr = &g_smartcard_arr_mutex; + TC_MUTEX_INIT(mutex_smartcard_arr, pnattr); + mutex_cb = &g_cb_mutex; + TC_MUTEX_INIT(mutex_cb, pnattr); + mutex_getattr = &g_getattr_mutex; + TC_MUTEX_INIT(mutex_getattr, pnattr); + } + + g_memset(wo_fpath,0,sizeof(char) * 512); + TC_MUTEX_LOCK(mutex_cb); + g_memset((callback *)g_callbacks,0,sizeof(callback) * MAX_PENDING); + TC_MUTEX_UNLOCK(mutex_cb); + + if (g_rdpdr_up) + { + return 0; + } + rdpdr_deinit(); + + rv = 0; + if (rv == 0) + { + /* Ascertain the PID of this process, for incorporating into the filename */ + pid = g_getpid(); + + /* Construct path and filename for the wait object */ + g_snprintf(wo_fpath,511,WO_PATH,pid); + + /* Create wait object */ + g_rdpdr_wait_obj = g_create_wait_obj(wo_fpath); + } + if (rv == 0) + { + make_stream(s); + init_stream(s, MAX_STREAM); + /* First, output a DR_CORE_SERVER_ANNOUNCE_REQ: */ + pdu = RDPDR_NEW(DR_CORE_SERVER_ANNOUNCE_REQ); + ((DR_CORE_SERVER_ANNOUNCE_REQ *)pdu)->ClientId = 0x00000001; + ((DR_CORE_SERVER_ANNOUNCE_REQ *)pdu)->out((DR_CORE_SERVER_ANNOUNCE_REQ *)pdu, s); + s_mark_end(s); + size = (int)(s->end - s->data); + LOG(5, ("[xrdp-chansrv]->rdpdr_init(): data out, sending " + "RDPDR_CONNECT (redir_msg_id = 1)")); + MDBGLOG("redir","INFO\t[%s()]: data out, sending (redir_msg_id = 1)",__func__); + TC_MUTEX_LOCK(mutex_out); + rv = send_channel_data(g_rdpdr_chan_id, s->data, size); + TC_MUTEX_UNLOCK(mutex_out); + //LOG(5,("[xrdp-chansrv]->rdpdr_init(): g_rdpdr_chan_id = %d",g_rdpdr_chan_id)); + MDBGLOG("redir","INFO\t[%s()]: g_rdpdr_chan_id = %d",__func__,g_rdpdr_chan_id); + if (rv != 0) + { + LOG(0, ("[xrdp-chansrv]->rdpdr_init(): send_channel_data failed " + "rv = %d", rv)); + MDBGLOG("redir","INFO\t[%s()]: send_channel_data failed " + "rv = %d", __func__, rv); + rv = 4; + } + //free_stream(s); + } + if (rv == 0) + { + g_rdpdr_up = 1; + make_stream(g_ins); + init_stream(g_ins, MAX_STREAM) + } + else + { + LOG(0, ("xrdp-chansrv: rdpdr_init: error on exit")); + MDBGLOG("redir","ERROR\t[%s()]: error on exit",__func__); + } + return rv; } /*****************************************************************************/ int APP_CC -dev_redir_deinit(void) -{ +rdpdr_deinit(void) { + int idx = 0; + + MDBGLOG("redir","INFO\t[%s()]: called",__func__); + + if (g_rdpdr_wait_obj > -1) { + g_delete_wait_obj(g_rdpdr_wait_obj); + } + + g_rdpdr_up = 0; + g_rdpdr_wait_obj = -1; + g_received_close_pdu = 0; + g_client_announce_reply_received = 0; + g_client_name_request_received = 0; + g_user_loggedon_sent = 0; + g_client_id = 0x0001; + + if (g_client_computer_name != NULL) { + //g_free(g_client_computer_name); + g_client_computer_name = (char *)NULL; + } + + if (g_ins != NULL) { + //free_stream(g_ins); + g_ins = (struct stream *)NULL; + } + + TC_MUTEX_LOCK(mutex_fs_arr); + if (g_fs_arr != NULL && g_fs_count > 0) { + for (idx = 0; idx < g_fs_count; idx++) { + if (g_fs_arr[idx] != NULL && g_fs_arr[idx]->mountpoint != NULL && g_strlen(g_fs_arr[idx]->mountpoint) > 0) { + fuse_unmount(g_fs_arr[idx]->mountpoint, g_fs_arr[idx]->ch); + } + } + } + if (g_fs_arr != NULL && g_fs_count > 0) { + for (idx = 0; idx < g_fs_count; idx++) { + if (g_fs_arr[idx] != NULL) { + if (g_fs_arr[idx]->child_pid > 0) { + g_waitpid(g_fs_arr[idx]->child_pid); + } + g_fs_arr[idx]->g_fs = NULL; + if (g_fs_arr[idx]->ccon != NULL) { + //trans_delete(g_fs_arr[idx]->ccon); + g_free(g_fs_arr[idx]->ccon); + g_fs_arr[idx]->ccon = NULL; + } + if (g_fs_arr[idx]->mountpoint != NULL) { + g_free(g_fs_arr[idx]->mountpoint); + g_fs_arr[idx]->mountpoint = NULL; + } + if (g_fs_arr[idx]->dos_name != NULL) { + g_free(g_fs_arr[idx]->dos_name); + g_fs_arr[idx]->dos_name = NULL; + } + if (g_fs_arr[idx]->fuse != NULL) { + g_free(g_fs_arr[idx]->fuse); + g_fs_arr[idx]->fuse = NULL; + } + if (g_fs_arr[idx]->ch != NULL) { + g_free(g_fs_arr[idx]->ch); + g_fs_arr[idx]->ch = NULL; + } + if (g_fs_arr[idx]->host != NULL) { + g_free(g_fs_arr[idx]->host); + g_fs_arr[idx]->host = NULL; + } + if (g_fs_arr[idx]->base_path != NULL) { + g_free(g_fs_arr[idx]->base_path); + g_fs_arr[idx]->base_path = NULL; + } + if (g_fs_arr[idx]->progname != NULL) { + g_free(g_fs_arr[idx]->progname); + g_fs_arr[idx]->progname = NULL; + } + g_free(g_fs_arr[idx]); + } + } + } + TC_MUTEX_UNLOCK(mutex_fs_arr); + + TC_MUTEX_LOCK(mutex_port_arr); + if (g_port_arr != NULL && g_port_count > 0) { + for (idx = 0; idx < g_port_count; idx++) { + if (g_port_arr[idx] != NULL) { + if (g_port_arr[idx]->child_pid > 0) { + g_waitpid(g_port_arr[idx]->child_pid); + } + g_port_arr[idx]->g_port = NULL; + if (g_port_arr[idx]->ccon != NULL) { + //trans_delete(g_port_arr[idx]->ccon); + g_free(g_port_arr[idx]->ccon); + g_port_arr[idx]->ccon = NULL; + } + if (g_port_arr[idx]->file_path != NULL) { + g_free(g_port_arr[idx]->file_path); + g_port_arr[idx]->file_path = NULL; + } + if (g_port_arr[idx]->dos_name != NULL) { + g_free(g_port_arr[idx]->dos_name); + g_port_arr[idx]->dos_name = NULL; + } + g_free(g_port_arr[idx]); + } + } + } + TC_MUTEX_UNLOCK(mutex_port_arr); + + TC_MUTEX_LOCK(mutex_printer_arr); + if (g_printer_arr != NULL && g_printer_count > 0) { + for (idx = 0; idx < g_printer_count; idx++) { + if (g_printer_arr[idx] != NULL) { + if (g_printer_arr[idx]->child_pid > 0) { + g_waitpid(g_printer_arr[idx]->child_pid); + } + g_printer_arr[idx]->g_printer = NULL; + if (g_printer_arr[idx]->ccon != NULL) { + //trans_delete(g_printer_arr[idx]->ccon); + g_free(g_printer_arr[idx]->ccon); + g_printer_arr[idx]->ccon = NULL; + } + if (g_printer_arr[idx]->file_path != NULL) { + g_free(g_printer_arr[idx]->file_path); + g_printer_arr[idx]->file_path = NULL; + } + if (g_printer_arr[idx]->dos_name != NULL) { + g_free(g_printer_arr[idx]->dos_name); + g_printer_arr[idx]->dos_name = NULL; + } + g_free(g_printer_arr[idx]); + } + } + } + TC_MUTEX_UNLOCK(mutex_printer_arr); + + TC_MUTEX_LOCK(mutex_smartcard_arr); + if (g_smartcard_arr != NULL && g_smartcard_count > 0) { + for (idx = 0; idx < g_smartcard_count; idx++) { + if (g_smartcard_arr[idx] != NULL) { + if (g_smartcard_arr[idx]->child_pid > 0) { + g_waitpid(g_smartcard_arr[idx]->child_pid); + } + g_smartcard_arr[idx]->g_sc = NULL; + if (g_smartcard_arr[idx]->ccon != NULL) { + //trans_delete(g_smartcard_arr[idx]->ccon); + g_free(g_smartcard_arr[idx]->ccon); + g_smartcard_arr[idx]->ccon = NULL; + } + if (g_smartcard_arr[idx]->file_path != NULL) { + g_free(g_smartcard_arr[idx]->file_path); + g_smartcard_arr[idx]->file_path = NULL; + } + if (g_smartcard_arr[idx]->dos_name != NULL) { + g_free(g_smartcard_arr[idx]->dos_name); + g_smartcard_arr[idx]->dos_name = NULL; + } + g_free(g_smartcard_arr[idx]); + } + } + } + TC_MUTEX_UNLOCK(mutex_smartcard_arr); + return 0; } /*****************************************************************************/ int APP_CC -dev_redir_data_in(struct stream* s, int chan_id, int chan_flags, int length, - int total_length) -{ - return 0; +rdpdr_data_in(struct stream * s, int chan_id, int chan_flags, int length, int total_length) { + int rdpdr_msg_id = 0; + int rdpdr_msg_len = 0; + int rdpdr_msg_status = 0; + int rv = 0; + int idx = 0; + int size = 0; + int rdp_opcode = 0; + int send_partial = 0; + struct stream * ls = (struct stream *)NULL; + struct stream * ts = (struct stream *)NULL; + struct stream * vs = (struct stream *)NULL; + char * p = (char *)NULL; + int devidx = 0; + int fault = 0; + int suppress = 0; + int fhandle = 0; + int uniqid = 0; + uint32_t crc32 = 0x00000000; + uint32_t magic = 0x00000000; + uint32_t device_id = 0x00000000; + BYTE buf[MAX_STREAM]; + DR_CORE_SERVER_ANNOUNCE_RSP * creply = (DR_CORE_SERVER_ANNOUNCE_RSP *)NULL; + DR_CORE_CLIENT_NAME_REQ * cname = (DR_CORE_CLIENT_NAME_REQ *)NULL; + RDPDR_HEADER * hdr = (RDPDR_HEADER *)NULL; + DR_CORE_USER_LOGGEDON * ulo = (DR_CORE_USER_LOGGEDON *)NULL; + DR_CORE_CAPABILITY_REQ * capreq = (DR_CORE_CAPABILITY_REQ *)NULL; + CAPABILITY_SET * capset = (CAPABILITY_SET *)NULL; + GENERAL_CAPS_SET * generalcap = (GENERAL_CAPS_SET *)NULL; + PRINTER_CAPS_SET * printercap = (PRINTER_CAPS_SET *)NULL; + PORT_CAPS_SET * portcap = (PORT_CAPS_SET *)NULL; + DRIVE_CAPS_SET * drivecap = (DRIVE_CAPS_SET *)NULL; + SMARTCARD_CAPS_SET * smartcardcap = (SMARTCARD_CAPS_SET *)NULL; + + int g_test_mode = 1; + + void * pdu = (void *)NULL; + + MDBGLOG("redir","INFO\t[%s()]: called [%d, %d]\n\t\t--- chan_is 0x%8.8x; " + "chan_flags 0x%8.8x; length %d; total_length %d", __func__, g_getpid(), g_gettid(), + chan_id, chan_flags, length, total_length); + + if ((chan_flags & 3) == 3) + { + ls = s; + } + else + { + if (chan_flags & 1) + { + init_stream(g_ins, total_length) + } + in_uint8a(s, g_ins->end, length); + g_ins->end += length; + if ((chan_flags & 2) == 0) + { + return 0; + } + ls = g_ins; + } + if (g_client_announce_reply_received < 1) { + creply = RDPDR_NEW(DR_CORE_SERVER_ANNOUNCE_RSP); + get_DR_CORE_SERVER_ANNOUNCE_RSP(creply, ls); + g_client_id = creply->ClientId; + g_client_announce_reply_received = 1; + MDBGLOG("redir","\nINFO\t[%s()]: **** Header.Component = 0x%8.8x\n * Header.PacketId = 0x%8.8x\n * ClientId = 0x%8.8x\n * VersionMajor = 0x%8.8x\n * VersionMinor = 0x%8.8x\n",__func__,creply->Header.Component,creply->Header.PacketId,creply->ClientId,creply->VersionMajor,creply->VersionMinor); + } + else if (g_client_name_request_received < 1) { + DR_CORE_CLIENT_NAME_REQ tname; + //cname = RDPDR_NEW(DR_CORE_CLIENT_NAME_REQ); + cname = &tname; + g_memset(cname,0,sizeof(DR_CORE_CLIENT_NAME_REQ)); + construct_DR_CORE_CLIENT_NAME_REQ(cname); + get_DR_CORE_CLIENT_NAME_REQ(cname, ls); + g_client_name_request_received = 1; + g_client_computer_name = (char *)g_malloc(sizeof(char) * cname->ComputerNameLen,1); + if (cname->UnicodeFlag > 0) { + for (idx = 0; idx < (cname->ComputerNameLen / 2); idx++) { + g_client_computer_name[idx] = cname->ComputerName[(idx * 2)]; + } + } + else { + for (idx = 0; idx < cname->ComputerNameLen; idx++) { + g_client_computer_name[idx] = cname->ComputerName[idx]; + } + } + MDBGLOG("redir","\nINFO\t[%s()]: **** Header.Component = 0x%8.8x\n * Header.PacketId = 0x%8.8x\n * UnicodeFlag = 0x%8.8x\n * CodePage = 0x%8.8x\n * ComputerNameLen = 0x%8.8x\n * ComputerName = %s\n",__func__,cname->Header.Component,cname->Header.PacketId,cname->UnicodeFlag,cname->CodePage,cname->ComputerNameLen,g_client_computer_name); + + if (g_core_capabilities_requested < 1) { + capreq = RDPDR_NEW(DR_CORE_CAPABILITY_REQ); + capreq->numCapabilities = 5; + + generalcap = RDPDR_NEW(GENERAL_CAPS_SET); + printercap = RDPDR_NEW(PRINTER_CAPS_SET); + portcap = RDPDR_NEW(PORT_CAPS_SET); + drivecap = RDPDR_NEW(DRIVE_CAPS_SET); + smartcardcap = RDPDR_NEW(SMARTCARD_CAPS_SET); + + make_stream(ts); + init_stream(ts, MAX_STREAM); + send_RDPDR_HEADER(&(capreq->Header), ts); + capreq->numCapabilities = 5; + out_uint16_le(ts, capreq->numCapabilities); + out_uint16_le(ts, capreq->Padding); + + generalcap->Header.CapabilityLength = 0x2c; + generalcap->osType = 0x00000002; + generalcap->osVersion = 0x00000000; + generalcap->protocolMajorVersion = 0x0001; + generalcap->protocolMinorVersion = 0x000c; + generalcap->ioCode1 = 0x0000ffff; + generalcap->ioCode2 = 0x00000000; + generalcap->extendedPDU = 0x00000007; + generalcap->extraFlags1 = ENABLE_ASYNCIO; + generalcap->extraFlags2 = 0x00000000; + generalcap->SpecialTypeDeviceCap = 0x00000002; + + out_uint16_le(ts, generalcap->Header.CapabilityType); + out_uint16_le(ts, generalcap->Header.CapabilityLength); + out_uint32_le(ts, generalcap->Header.Version); + out_uint32_le(ts, generalcap->osType); + out_uint32_le(ts, generalcap->osVersion); + out_uint16_le(ts, generalcap->protocolMajorVersion); + out_uint16_le(ts, generalcap->protocolMinorVersion); + out_uint32_le(ts, generalcap->ioCode1); + out_uint32_le(ts, generalcap->ioCode2); + out_uint32_le(ts, generalcap->extendedPDU); + out_uint32_le(ts, generalcap->extraFlags1); + out_uint32_le(ts, generalcap->extraFlags2); + out_uint32_le(ts, generalcap->SpecialTypeDeviceCap); + + out_uint16_le(ts, printercap->Header.CapabilityType); + out_uint16_le(ts, printercap->Header.CapabilityLength); + out_uint32_le(ts, printercap->Header.Version); + + out_uint16_le(ts, portcap->Header.CapabilityType); + out_uint16_le(ts, portcap->Header.CapabilityLength); + out_uint32_le(ts, portcap->Header.Version); + + out_uint16_le(ts, drivecap->Header.CapabilityType); + out_uint16_le(ts, drivecap->Header.CapabilityLength); + out_uint32_le(ts, drivecap->Header.Version); + + out_uint16_le(ts, smartcardcap->Header.CapabilityType); + out_uint16_le(ts, smartcardcap->Header.CapabilityLength); + out_uint32_le(ts, smartcardcap->Header.Version); + + s_mark_end(ts); + size = (int)(ts->end - ts->data); + TC_MUTEX_LOCK(mutex_out); + rv = send_channel_data(g_rdpdr_chan_id, ts->data, size); + TC_MUTEX_UNLOCK(mutex_out); + MDBGLOG("redir","INFO\t[%s()]: ^^ DR_CORE_CAPABILITY_REQ sent (rv = %d).",__func__,rv); + // g_hexdump_file("/tmp/redir_hexdump.log", ts->data, size); + g_core_capabilities_requested = 1; + //free_stream(ts); + } + + if (g_user_loggedon_sent < 1) { + ulo = RDPDR_NEW(DR_CORE_USER_LOGGEDON); + make_stream(ts); + init_stream(ts, MAX_STREAM); + ulo->out(ulo, ts); + s_mark_end(ts); + size = (int)(ts->end - ts->data); + TC_MUTEX_LOCK(mutex_out); + rv = send_channel_data(g_rdpdr_chan_id, ts->data, size); + TC_MUTEX_UNLOCK(mutex_out); + MDBGLOG("redir","INFO\t[%s()]: ^^ DR_CORE_USER_LOGGEDON sent (rv = %d).",__func__,rv); + g_user_loggedon_sent = 1; + //free_stream(ts); + } + } + else { + + RDPDR_HEADER thdr; + g_memset(&thdr,0,sizeof(RDPDR_HEADER)); + hdr = &thdr; + construct_RDPDR_HEADER(&thdr); + get_RDPDR_HEADER(hdr, ls); + + MDBGLOG("redir", "INFO\t[%s()]: hdr->(Component = 0x%8.8x, PacketId = 0x%8.8x)", __func__, thdr.Component, thdr.PacketId); + + if (hdr->Component == RDPDR_CTYP_CORE) { + switch (hdr->PacketId) { + case PAKID_CORE_SERVER_ANNOUNCE: + MDBGLOG("redir","INFO\t[%s()]: - hdr->PacketId = 0x%8.8x (PAKID_CORE_SERVER_ANNOUNCE)",__func__,hdr->PacketId); + // rv = rdpdr_process_SERVER_ANNOUNCE(ls); + break; + case PAKID_CORE_CLIENTID_CONFIRM: + MDBGLOG("redir","INFO\t[%s()]: - hdr->PacketId = 0x%8.8x (PAKID_CORE_CLIENTID_CONFIRM)",__func__,hdr->PacketId); + // rv = rdpdr_process_CLIENTID_CONFIRM(ls); + break; + case PAKID_CORE_CLIENT_NAME: + MDBGLOG("redir","INFO\t[%s()]: - hdr->PacketId = 0x%8.8x (PAKID_CORE_CLIENT_NAME)",__func__,hdr->PacketId); + // rv = rdpdr_process_CLIENT_NAME(ls); + break; + case PAKID_CORE_DEVICELIST_ANNOUNCE: + MDBGLOG("redir","INFO\t[%s()]: - hdr->PacketId = 0x%8.8x (PAKID_CORE_DEVICELIST_ANNOUNCE)",__func__,hdr->PacketId); + { + int j = 0; + int id = 0; + char * dname = (char *)NULL; + size = ls->end - ls->p; + // g_hexdump_file("/tmp/taskq_devicelist.hexdump", ls->p, size); + rv = rdpdr_process_DEVICELIST_ANNOUNCE(ls); + TC_MUTEX_LOCK(mutex_client_devicelist); + if (g_client_devicelist->DeviceCount > 0) { + MDBGLOG("redir","INFO\t[%s()]: - g_port_count = %d;\n - g_fs_count = %d;\n - g_client_devicelist->DeviceCount = %d\n",__func__,g_port_count,g_fs_count,g_client_devicelist->DeviceCount); + for (j = 0; j < g_client_devicelist->DeviceCount; j++) if (g_client_devicelist->DeviceList[j] != NULL) { + id = g_client_devicelist->DeviceList[j]->DeviceId; + dname = g_client_devicelist->DeviceList[j]->PreferredDosName; + MDBGLOG("redir","\t[device #%d] - PreferredDosName = %s; DeviceId = 0x%8.8x",j,dname,id); + } + MDBGLOG("redir","\n"); + } + TC_MUTEX_UNLOCK(mutex_client_devicelist); + } + break; + case PAKID_CORE_DEVICE_REPLY: + MDBGLOG("redir","INFO\t[%s()]: - hdr->PacketId = 0x%8.8x (PAKID_CORE_DEVICE_REPLY)",__func__,hdr->PacketId); + rv = rdpdr_process_DEVICE_REPLY(ls); + break; + case PAKID_CORE_DEVICE_IOCOMPLETION: + MDBGLOG("redir","INFO\t[%s()]: - hdr->PacketId = 0x%8.8x (PAKID_CORE_DEVICE_IOCOMPLETION)",__func__,hdr->PacketId); + { + int opid = -1; + int tmp = 0; + int size = 0; + callback * cb = (callback *)NULL; + struct stream * t = (struct stream *)NULL; + struct stream * u = (struct stream *)NULL; + DEVICE_IOCOMPLETION ioc; + union _rsps { + DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP query_volume_information_rsp; + DR_DRIVE_QUERY_INFORMATION_RSP query_information_rsp; + DR_DRIVE_QUERY_DIRECTORY_RSP query_directory_rsp; + DR_DRIVE_SET_VOLUME_INFORMATION_RSP set_volume_information_rsp; + DR_DRIVE_SET_INFORMATION_RSP set_information_rsp; + DR_DRIVE_CLOSE_RSP close_rsp; + DR_DRIVE_CREATE_RSP drive_create_rsp; + DR_CREATE_RSP create_rsp; + DR_READ_RSP read_rsp; + DR_WRITE_RSP write_rsp; + DR_CONTROL_RSP control_rsp; + } rsps; + int new_opid = -1; + + g_memset(&ioc,0,sizeof(DEVICE_IOCOMPLETION)); + g_memset(&rsps,0,sizeof(union _rsps)); + + make_stream(u); + init_stream(u, MAX_STREAM); + + construct_DR_DEVICE_IOCOMPLETION(&ioc); + ioc.Header.Component = hdr->Component; + ioc.Header.PacketId = hdr->PacketId; + in_uint32_le(ls, ioc.DeviceId); + in_uint32_le(ls, ioc.CompletionId); + in_uint32_le(ls, ioc.IoStatus.Value); + + devidx = get_device_index(ioc.DeviceId); + opid = ioc.CompletionId; + + TC_MUTEX_LOCK(mutex_cb); + cb = &(g_callbacks[opid]); + rdp_opcode = cb->opcode; + uniqid = cb->uniqid; + cb->IoStatus.Value = ioc.IoStatus.Value; + + if (ioc.IoStatus.Fields.Sev == STATUS_SEVERITY_ERROR) { + fault = 1; + } + else if (ioc.IoStatus.Value >= STATUS_UNSUCCESSFUL && ioc.IoStatus.Value <= STATUS_SXS_CORRUPTION) { + fault = 1; + } + if (fault > 0) { + getattr_queue_t * tmp = (getattr_queue_t *)NULL; + const char * nterr = (const char *)ntstatus_string(ioc.IoStatus.Value); + rdp_opcode |= RDP_ERROR; + out_uint32_le(u, ioc.IoStatus.Value); + s_mark_end(u); + size = u->end - u->data; + fhandle = cb->FileId; + if (rdp_opcode == RDPFS_GETATTR || rdp_opcode == RDPFS_FGETATTR) { + device_id = (device_id > 0) ? device_id : g_client_devicelist->DeviceList[devidx]->DeviceId; + GETATTR_FIND(device_id, opid, tmp); + if (tmp != NULL) { + TC_MUTEX_LOCK(&(tmp->lock)); + GETATTR_CUT(tmp); + TC_MUTEX_UNLOCK(&(tmp->lock)); + TC_MUTEX_DEINIT(&(tmp->lock)); + g_free(tmp); + } + } + MDBGLOG("redir","INFO\t[%s()] (FAULT: \"%s\") reply: IoStatus = 0x%8.8x; rdp_opcode = 0x%8.8x; device_id = 0x%8.8x; fhandle = %d; uniqid = %d",__func__,nterr,ioc.IoStatus.Value,rdp_opcode,device_id,fhandle,uniqid); + } + else if (rdp_opcode == RDPFS_INIT || rdp_opcode == RDPPORT_INIT) { + DR_DRIVE_CREATE_RSP * rsp = (DR_DRIVE_CREATE_RSP *)NULL; + rsp = &rsps.drive_create_rsp; + construct_DR_DRIVE_CREATE_RSP(rsp); + g_memcpy(&(rsp->DeviceCreateResponse.DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + in_uint32_le(ls, rsp->DeviceCreateResponse.FileId); + in_uint8(ls, rsp->DeviceCreateResponse.Information); + cb->FileId = rsp->DeviceCreateResponse.FileId; + send_DR_DRIVE_CREATE_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + fhandle = rsp->DeviceCreateResponse.FileId; + MDBGLOG("redir","INFO\t[%s()] (RDPFS_INIT) reply: FileId = %d; Information = %d",__func__,rsp->DeviceCreateResponse.FileId,rsp->DeviceCreateResponse.Information); + } + else if (rdp_opcode == RDPFS_OPENDIR) { + DR_DRIVE_CREATE_RSP * rsp = (DR_DRIVE_CREATE_RSP *)NULL; + rsp = &rsps.drive_create_rsp; + construct_DR_DRIVE_CREATE_RSP(rsp); + g_memcpy(&(rsp->DeviceCreateResponse.DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + in_uint32_le(ls, rsp->DeviceCreateResponse.FileId); + in_uint8(ls, rsp->DeviceCreateResponse.Information); + cb->FileId = rsp->DeviceCreateResponse.FileId; + fhandle = rsp->DeviceCreateResponse.FileId; + send_DR_DRIVE_CREATE_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + } + else if (rdp_opcode == RDPFS_READDIR) { + int warning = 0; + DR_DRIVE_QUERY_DIRECTORY_RSP * rsp = (DR_DRIVE_QUERY_DIRECTORY_RSP *)NULL; + rsp = &rsps.query_directory_rsp; + fhandle = cb->FileId; + { + int i = 0; + int zlen = 0; + FILE_BOTH_DIR_INFORMATION * dirinfo = (FILE_BOTH_DIR_INFORMATION *)NULL; + LOCAL_STREAM(zs); + construct_DR_DRIVE_QUERY_DIRECTORY_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + rsp->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + rsp->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + rsp->out = &send_DR_DRIVE_QUERY_DIRECTORY_RSP; + in_uint32_le(ls, rsp->Length); + if (rsp->Length > 0) { + get_FILE_BOTH_DIR_INFORMATION(&(rsp->Buffer.both), ls); + } + if (rsp->Buffer.both.NextEntryOffset == 0) { + rsp->Buffer.both.NextEntryOffset = rsp->Length; + } + if (ioc.IoStatus.Value == STATUS_NO_MORE_FILES) { + g_no_more_files = 1; + } + send_DR_DRIVE_QUERY_DIRECTORY_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + if (g_no_more_files < 1) { + LOCAL_STREAM(r); + DR_DRIVE_QUERY_DIRECTORY_REQ ioreq; + construct_DR_DRIVE_QUERY_DIRECTORY_REQ(&ioreq); + ioreq.DeviceIoRequest.MajorFunction = IRP_MJ_DIRECTORY_CONTROL; + ioreq.DeviceIoRequest.MinorFunction = IRP_MN_QUERY_DIRECTORY; + TC_MUTEX_LOCK(mutex_client_devicelist); + TC_MUTEX_LOCK(mutex_fs_arr); + if (g_client_devicelist != NULL && g_client_devicelist->DeviceList != NULL && g_client_devicelist->DeviceList[devidx] != NULL) { + ioreq.DeviceIoRequest.DeviceId = g_client_devicelist->DeviceList[devidx]->DeviceId; + } + else if (g_fs_arr != NULL && g_fs_arr[0] != NULL) { + ioreq.DeviceIoRequest.DeviceId = g_fs_arr[0]->device_id; + } + TC_MUTEX_UNLOCK(mutex_client_devicelist); + ioreq.DeviceIoRequest.FileId = fhandle; + new_opid = get_opid(g_fs_arr[devidx]); + TC_MUTEX_UNLOCK(mutex_fs_arr); + ioreq.DeviceIoRequest.CompletionId = new_opid; + ioreq.FsInformationClass = FileBothDirectoryInformation; + ioreq.InitialQuery = 0x00; + ioreq.PathLength = 0; + g_memcpy((callback *)(&(g_callbacks[new_opid])),(callback *)(&(g_callbacks[opid])),sizeof(callback)); + g_callbacks[new_opid].opid = new_opid; + g_callbacks[new_opid].CompletionId = new_opid; + g_memset(&(g_callbacks[opid]),0,sizeof(callback)); + g_callbacks[opid].opid = -1; + send_DR_DRIVE_QUERY_DIRECTORY_REQ(&ioreq, r); + s_mark_end(r); + TC_MUTEX_LOCK(mutex_out); + send_channel_data(g_rdpdr_chan_id, r->data, (int)(r->end - r->data)); + TC_MUTEX_UNLOCK(mutex_out); + } + else { + g_no_more_files = 0; + } + } + } + else if (rdp_opcode == RDPFS_RELEASEDIR) { + DR_DRIVE_CLOSE_RSP * rsp = (DR_DRIVE_CLOSE_RSP *)NULL; + rsp = &rsps.close_rsp; + g_memcpy(&(rsp->DeviceCloseResponse.DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + construct_DR_DRIVE_CLOSE_RSP(rsp); + send_DR_DRIVE_CLOSE_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + //MDBGLOG("redir","INFO\t[%s()]: (RDPFS_RELEASEDIR) reply",__func__); + } + else if (rdp_opcode == RDPFS_CREATE) { + DR_DRIVE_CREATE_RSP * rsp = (DR_DRIVE_CREATE_RSP *)NULL; + rsp = &rsps.drive_create_rsp; + construct_DR_DRIVE_CREATE_RSP(rsp); + g_memcpy(&(rsp->DeviceCreateResponse.DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + in_uint32_le(ls, rsp->DeviceCreateResponse.FileId); + in_uint8(ls, rsp->DeviceCreateResponse.Information); + cb->FileId = rsp->DeviceCreateResponse.FileId; + fhandle = rsp->DeviceCreateResponse.FileId; + send_DR_DRIVE_CREATE_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("parent","INFO\t[%s()] (RDPFS_CREATE) reply: FileId = %d; Information = %d; fhandle = %d",__func__,rsp->DeviceCreateResponse.FileId,rsp->DeviceCreateResponse.Information,fhandle); + //MDBGLOG("redir","INFO\t[%s()]: (RDPFS_CREATE) reply",__func__); + } + else if (rdp_opcode == RDPFS_OPEN || rdp_opcode == RDPPORT_OPEN) { + DR_DRIVE_CREATE_RSP * rsp = (DR_DRIVE_CREATE_RSP *)NULL; + rsp = &rsps.drive_create_rsp; + construct_DR_DRIVE_CREATE_RSP(rsp); + g_memcpy(&(rsp->DeviceCreateResponse.DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + in_uint32_le(ls, rsp->DeviceCreateResponse.FileId); + in_uint8(ls, rsp->DeviceCreateResponse.Information); + cb->FileId = rsp->DeviceCreateResponse.FileId; + fhandle = rsp->DeviceCreateResponse.FileId; + send_DR_DRIVE_CREATE_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + //MDBGLOG("parent","INFO\t[%s()]: (RDPFS_OPEN) reply (FileId = %d; Information = %d; fhandle = %d)",__func__,rsp->DeviceCreateResponse.FileId,rsp->DeviceCreateResponse.Information,fhandle); + //// g_hexdump_file("/tmp/taskq_dev_open.hexdump",u->data,size); + } + else if (rdp_opcode == RDPFS_READ || rdp_opcode == RDPPORT_READ) { + DR_DRIVE_READ_RSP * rsp = (DR_DRIVE_READ_RSP *)NULL; + rsp = &rsps.read_rsp; + construct_DR_READ_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + rsp->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + rsp->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + rsp->out = &send_DR_READ_RSP; + in_uint32_le(ls, rsp->Length); + if (rsp->Length > 0) { + rsp->ReadData = (BYTE *)g_malloc(sizeof(BYTE) * rsp->Length, 1); + in_uint8a(ls, rsp->ReadData, rsp->Length); + } + send_DR_READ_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + // g_hexdump_file("/tmp/taskq_read.hexdump", u->data, size); + MDBGLOG("redir","INFO\t[%s()] (RDPFS_READ) reply (size = %d; rsp->Length = %d; rsp->ReadData = \"%s\"; rsp->DeviceIoReply.IoStatus = 0x%8.8x)",__func__,size,rsp->Length,rsp->ReadData,rsp->DeviceIoReply.IoStatus.Value); + } + else if (rdp_opcode == RDPFS_WRITE || rdp_opcode == RDPPORT_WRITE) { + DR_DRIVE_WRITE_RSP * rsp = (DR_DRIVE_WRITE_RSP *)NULL; + rsp = &rsps.write_rsp; + construct_DR_WRITE_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + rsp->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + rsp->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + rsp->out = &send_DR_WRITE_RSP; + in_uint32_le(ls, rsp->Length); + send_DR_WRITE_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("redir","INFO\t[%s()] (RDPFS_WRITE) reply",__func__); + } + else if (rdp_opcode == RDPFS_GETATTR || rdp_opcode == RDPFS_FGETATTR) { + getattr_queue_t * tmp = (getattr_queue_t *)NULL; + DR_DRIVE_QUERY_INFORMATION_RSP * rsp = (DR_DRIVE_QUERY_INFORMATION_RSP *)NULL; + DR_DRIVE_QUERY_INFORMATION_REQ ioreq; + LOCAL_STREAM(r); + rsp = &(rsps.query_information_rsp); + construct_DR_DRIVE_QUERY_INFORMATION_RSP(rsp); + g_memcpy(rsp, &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + g_memset(&ioreq,0,sizeof(DR_DRIVE_QUERY_INFORMATION_REQ)); + TC_MUTEX_LOCK(mutex_client_devicelist); + device_id = (device_id > 0) ? device_id : g_client_devicelist->DeviceList[devidx]->DeviceId; + TC_MUTEX_UNLOCK(mutex_client_devicelist); + TC_MUTEX_LOCK(mutex_getattr); + GETATTR_FIND(device_id, opid, tmp); + if (tmp == NULL) { + tmp = GETATTR_CREATE(); + if (tmp != NULL) { + GETATTR_INIT(tmp); + TC_MUTEX_LOCK(&(tmp->lock)); + tmp->basic_done = 0; + tmp->device_id = device_id; + tmp->uniqid = uniqid; + tmp->opid = opid; + tmp->fhandle = g_callbacks[opid].FileId; + TC_MUTEX_UNLOCK(&(tmp->lock)); + } + } + if (tmp->basic_done < 1) { + TC_MUTEX_LOCK(&(tmp->lock)); + rsp = &(tmp->rsp); + g_memset(rsp,0,sizeof(DR_DRIVE_QUERY_INFORMATION_RSP)); + construct_DR_DRIVE_QUERY_INFORMATION_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + rsp->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + rsp->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + rsp->out = &send_DR_DRIVE_QUERY_INFORMATION_RSP; + in_uint32_le(ls, rsp->Length); + if (rsp->Length > 0) { + in_uint8a(ls, &(rsp->Buffer.all.BasicInformation), rsp->Length); + } + suppress = 1; + tmp->basic_done = 1; + construct_DR_DRIVE_QUERY_INFORMATION_REQ(&ioreq); + ioreq.DeviceIoRequest.MajorFunction = IRP_MJ_QUERY_INFORMATION; + TC_MUTEX_LOCK(mutex_client_devicelist); + TC_MUTEX_LOCK(mutex_fs_arr); + if (g_client_devicelist != NULL && g_client_devicelist->DeviceList != NULL && g_client_devicelist->DeviceList[devidx] != NULL) { + ioreq.DeviceIoRequest.DeviceId = g_client_devicelist->DeviceList[devidx]->DeviceId; + } + else if (g_fs_arr != NULL && g_fs_arr[0] != NULL) { + ioreq.DeviceIoRequest.DeviceId = g_fs_arr[0]->device_id; + } + TC_MUTEX_UNLOCK(mutex_fs_arr); + TC_MUTEX_UNLOCK(mutex_client_devicelist); + new_opid = opid; + ioreq.DeviceIoRequest.CompletionId = new_opid; + g_callbacks[new_opid].opid = new_opid; + g_callbacks[new_opid].CompletionId = new_opid; + g_callbacks[new_opid].uniqid = g_callbacks[opid].uniqid; + g_callbacks[new_opid].FileId = g_callbacks[opid].FileId; + ioreq.DeviceIoRequest.FileId = tmp->fhandle; + ioreq.FsInformationClass = FileStandardInformation; + send_DR_DRIVE_QUERY_INFORMATION_REQ(&ioreq, r); + s_mark_end(r); + TC_MUTEX_LOCK(mutex_out); + send_channel_data(g_rdpdr_chan_id, r->data, (int)(r->end - r->data)); + TC_MUTEX_UNLOCK(mutex_out); + tmp->uniqid = uniqid; + tmp->opid = opid; + tmp->opcode = rdp_opcode; + g_callbacks[opid].opid = 0; + TC_MUTEX_UNLOCK(&(tmp->lock)); + } + else { + int len = 0; + char * iptr = NULL; + char * optr = NULL; + int inum = 0; + int onum = 0; + TC_MUTEX_LOCK(&(tmp->lock)); + rsp = &(tmp->rsp); + in_uint32_le(ls, len); + if (len > 0) { + in_uint8a(ls, &(rsp->Buffer.all.StandardInformation), len); + } + rsp->Buffer.all.NameInformation.FileNameLength = (g_strlen(g_callbacks[opid].fname) + 1) * 2; + iptr = g_callbacks[opid].fname; + optr = rsp->Buffer.all.NameInformation.FileName; + inum = g_strlen(g_callbacks[opid].fname); + onum = rsp->Buffer.all.NameInformation.FileNameLength; + g_outstr(&optr, &onum, &iptr, &inum); + uniqid = tmp->uniqid; + rdp_opcode |= tmp->opcode; + rsp->Length = sizeof(FILE_ALL_INFORMATION) + rsp->Buffer.all.NameInformation.FileNameLength; + send_DR_DRIVE_QUERY_INFORMATION_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + tmp->basic_done = 0; + GETATTR_CUT(tmp); + TC_MUTEX_UNLOCK(&(tmp->lock)); + TC_MUTEX_DEINIT(&(tmp->lock)); + g_free(tmp); + } + TC_MUTEX_UNLOCK(mutex_getattr); + } + else if (rdp_opcode == RDPFS_SETATTR) { + DR_DRIVE_CONTROL_RSP * rsp = (DR_DRIVE_CONTROL_RSP *)NULL; + rsp = &rsps.control_rsp; + construct_DR_CONTROL_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + send_DR_CONTROL_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_SETATTR) reply",__func__); + } + else if (rdp_opcode == RDPFS_MKNOD) { + DR_DRIVE_CREATE_RSP * rsp = (DR_DRIVE_CREATE_RSP *)NULL; + rsp = &rsps.drive_create_rsp; + construct_DR_DRIVE_CREATE_RSP(rsp); + g_memcpy(&(rsp->DeviceCreateResponse.DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + send_DR_DRIVE_CREATE_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_MKNOD) reply",__func__); + } + else if (rdp_opcode == RDPFS_MKDIR) { + DR_DRIVE_CREATE_RSP * rsp = (DR_DRIVE_CREATE_RSP *)NULL; + rsp = &rsps.drive_create_rsp; + construct_DR_DRIVE_CREATE_RSP(rsp); + g_memcpy(&(rsp->DeviceCreateResponse.DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + in_uint32_le(ls, rsp->DeviceCreateResponse.FileId); + in_uint8(ls, rsp->DeviceCreateResponse.Information); + cb->FileId = rsp->DeviceCreateResponse.FileId; + fhandle = rsp->DeviceCreateResponse.FileId; + send_DR_DRIVE_CREATE_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_MKDIR) replying: FileId = %d; fhandle = %d",__func__,rsp->DeviceCreateResponse.FileId,fhandle); + } + else if (rdp_opcode == RDPFS_UNLINK) { + DR_DRIVE_SET_INFORMATION_RSP * rsp = (DR_DRIVE_SET_INFORMATION_RSP *)NULL; + rsp = &rsps.set_information_rsp; + construct_DR_DRIVE_SET_INFORMATION_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + send_DR_DRIVE_SET_INFORMATION_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_UNLINK) reply",__func__,rsp->Length); + } + else if (rdp_opcode == RDPFS_RELEASE || rdp_opcode == RDPPORT_CLOSE) { + DR_DRIVE_CLOSE_RSP * rsp = (DR_DRIVE_CLOSE_RSP *)NULL; + rsp = &rsps.close_rsp; + construct_DR_DRIVE_CLOSE_RSP(rsp); + g_memcpy(&(rsp->DeviceCloseResponse.DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + send_DR_DRIVE_CLOSE_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + } + else if (rdp_opcode == RDPFS_RMDIR) { + DR_DRIVE_SET_INFORMATION_RSP * rsp = (DR_DRIVE_SET_INFORMATION_RSP *)NULL; + rsp = &rsps.set_information_rsp; + construct_DR_DRIVE_SET_INFORMATION_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + send_DR_DRIVE_SET_INFORMATION_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_RMDIR) reply",__func__); + } + else if (rdp_opcode == RDPFS_SYMLINK) { + DR_DRIVE_CREATE_RSP * rsp = (DR_DRIVE_CREATE_RSP *)NULL; + rsp = &rsps.drive_create_rsp; + construct_DR_DRIVE_CREATE_RSP(rsp); + g_memcpy(&(rsp->DeviceCreateResponse.DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + send_DR_DRIVE_CREATE_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_SYMLINK) reply",__func__); + } + else if (rdp_opcode == RDPFS_RENAME) { + DR_DRIVE_SET_INFORMATION_RSP * rsp = (DR_DRIVE_SET_INFORMATION_RSP *)NULL; + rsp = &rsps.set_information_rsp; + construct_DR_DRIVE_SET_INFORMATION_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + send_DR_DRIVE_SET_INFORMATION_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_RENAME) reply",__func__); + } + else if (rdp_opcode == RDPFS_LINK) { + DR_DRIVE_CREATE_RSP * rsp = (DR_DRIVE_CREATE_RSP *)NULL; + rsp = &rsps.drive_create_rsp; + construct_DR_DRIVE_CREATE_RSP(rsp); + g_memcpy(&(rsp->DeviceCreateResponse.DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + send_DR_DRIVE_CREATE_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_LINK) reply",__func__); + } + else if (rdp_opcode == RDPFS_CHMOD) { + DR_CONTROL_RSP * rsp = (DR_CONTROL_RSP *)NULL; + rsp = &rsps.control_rsp; + construct_DR_CONTROL_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + send_DR_CONTROL_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_CHMOD) reply",__func__); + } + else if (rdp_opcode == RDPFS_CHOWN) { + DR_CONTROL_RSP * rsp = (DR_CONTROL_RSP *)NULL; + rsp = &rsps.control_rsp; + construct_DR_CONTROL_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + send_DR_CONTROL_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_CHOWN) reply",__func__); + } + else if (rdp_opcode == RDPFS_TRUNCATE) { + DR_DRIVE_SET_INFORMATION_RSP * rsp = (DR_DRIVE_SET_INFORMATION_RSP *)NULL; + rsp = &rsps.set_information_rsp; + construct_DR_DRIVE_SET_INFORMATION_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + in_uint32_le(ls, rsp->Length); + send_DR_DRIVE_SET_INFORMATION_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_TRUNCATE) reply",__func__); + } + else if (rdp_opcode == RDPFS_UTIME) { + callback * lcb = (callback *)NULL; + lcb = &(g_callbacks[opid]); + if (lcb->userdata != NULL) { + DR_DRIVE_SET_INFORMATION_RSP * rsp = (DR_DRIVE_SET_INFORMATION_RSP *)NULL; + rsp = &rsps.set_information_rsp; + construct_DR_DRIVE_SET_INFORMATION_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + send_DR_DRIVE_SET_INFORMATION_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + g_free(lcb->userdata); + lcb->userdata = NULL; + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_UTIME) reply",__func__); + } + else { + DR_DRIVE_SET_INFORMATION_REQ ioreq; + FILE_BASIC_INFORMATION * finfo; + int len = 0; + struct tm * t1 = NULL; + struct tm * t2 = NULL; + struct tm * t3 = NULL; + struct tm * t4 = NULL; + char * ttime1 = NULL; + char * ttime2 = NULL; + char * ttime3 = NULL; + char * ttime4 = NULL; + time_t tt1 = 0; + time_t tt2 = 0; + time_t tt3 = 0; + time_t tt4 = 0; + LOCAL_STREAM(r); + + suppress = 1; + + finfo = g_malloc(sizeof(FILE_BASIC_INFORMATION), 1); + lcb->userdata = (BYTE *)finfo; + in_uint32_le(ls, len); + if (len > 0) { + in_uint8a(ls,finfo,len); + } + + construct_DR_DRIVE_SET_INFORMATION_REQ(&ioreq); + ioreq.DeviceIoRequest.MajorFunction = IRP_MJ_SET_INFORMATION; + TC_MUTEX_LOCK(mutex_client_devicelist); + TC_MUTEX_LOCK(mutex_fs_arr); + if (g_client_devicelist != NULL && g_client_devicelist->DeviceList != NULL && g_client_devicelist->DeviceList[devidx] != NULL) { + ioreq.DeviceIoRequest.DeviceId = g_client_devicelist->DeviceList[devidx]->DeviceId; + } + else if (g_fs_arr != NULL && g_fs_arr[0] != NULL) { + ioreq.DeviceIoRequest.DeviceId = g_fs_arr[0]->device_id; + } + TC_MUTEX_UNLOCK(mutex_fs_arr); + TC_MUTEX_UNLOCK(mutex_client_devicelist); + ioreq.DeviceIoRequest.CompletionId = opid; + ioreq.DeviceIoRequest.FileId = lcb->FileId; + ioreq.FsInformationClass = FileBasicInformation; + ioreq.Length = sizeof(FILE_BASIC_INFORMATION); + + lcb->opcode = RDPFS_UTIME; + + ioreq.SetBuffer.BasicInformation.CreationTime = finfo->CreationTime; + ioreq.SetBuffer.BasicInformation.LastAccessTime = lcb->actime; + ioreq.SetBuffer.BasicInformation.LastWriteTime = lcb->modtime; + ioreq.SetBuffer.BasicInformation.ChangeTime = finfo->ChangeTime; + ioreq.SetBuffer.BasicInformation.FileAttributes = finfo->FileAttributes; + send_DR_DRIVE_SET_INFORMATION_REQ(&ioreq, r); + s_mark_end(r); + TC_MUTEX_LOCK(mutex_out); + send_channel_data(g_rdpdr_chan_id, r->data, (int)(r->end - r->data)); + TC_MUTEX_UNLOCK(mutex_out); + { + tt1 = FileTimeToUnix(ioreq.SetBuffer.BasicInformation.LastAccessTime); + tt2 = FileTimeToUnix(ioreq.SetBuffer.BasicInformation.LastWriteTime); + tt3 = FileTimeToUnix(ioreq.SetBuffer.BasicInformation.CreationTime); + tt4 = FileTimeToUnix(ioreq.SetBuffer.BasicInformation.ChangeTime); + t1 = gmtime(&tt1); + t2 = gmtime(&tt2); + t3 = gmtime(&tt3); + t4 = gmtime(&tt4); + ttime1 = asctime(t1); + ttime2 = asctime(t2); + ttime3 = asctime(t3); + ttime4 = asctime(t4); + MDBGLOG("redir"," ^^ (RDPFS_UTIME): ioreq.Length = %d; buf = \"%s\"; ioreq.DeviceIoRequest.FileId = %d; ioreq.SetBuffer.BasicInformation.LastAccessTime = %s; ioreq.SetBuffer.BasicInformation.LastWriteTime = %s; CreationTime = %s; ChangeTime = %s",ioreq.Length,buf,ioreq.DeviceIoRequest.FileId,ttime1,ttime2,ttime3,ttime4); + } + } + } + else if (rdp_opcode == RDPFS_STATFS) { + DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP * rsp = (DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP *)NULL; + rsp = &(rsps.query_volume_information_rsp); + construct_DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + in_uint32_le(ls, rsp->Length); + if (rsp->Length > 0) { + in_uint8a(ls, (char *)(rsp->Buffer.bytes), rsp->Length); + } + send_DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_STATFS) reply",__func__); + } + else if (rdp_opcode == RDPFS_FLUSH) { + DR_CONTROL_RSP * rsp = (DR_CONTROL_RSP *)NULL; + rsp = &rsps.control_rsp; + construct_DR_CONTROL_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + send_DR_CONTROL_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_FLUSH) reply",__func__); + } + else if (rdp_opcode == RDPFS_FSYNC) { + DR_CONTROL_RSP * rsp = (DR_CONTROL_RSP *)NULL; + rsp = &rsps.control_rsp; + construct_DR_CONTROL_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + send_DR_CONTROL_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_FSYNC) reply",__func__); + } + else if (rdp_opcode == RDPFS_FSCTL) { + DR_CONTROL_RSP * rsp = (DR_CONTROL_RSP *)NULL; + rsp = &rsps.control_rsp; + construct_DR_CONTROL_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + rsp->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + rsp->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + rsp->out = &send_DR_CONTROL_RSP; + in_uint32_le(ls, rsp->OutputBufferLength); + if (rsp->OutputBufferLength > 0) { + rsp->OutputBuffer = (BYTE *)g_malloc(sizeof(BYTE) * rsp->OutputBufferLength, 1); + in_uint8a(ls, rsp->OutputBuffer, rsp->OutputBufferLength); + } + send_DR_CONTROL_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + // g_hexdump_file("/tmp/taskq_fsctl.hexdump", u->data, size); + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_FSCTL) reply (size = %d; rsp->OutputBufferLength = %d; rsp->DeviceIoReply.IoStatus = 0x%8.8x)",__func__,size,rsp->OutputBufferLength,rsp->DeviceIoReply.IoStatus.Value); + } + else if (rdp_opcode == RDPPORT_IOCTL) { + DR_CONTROL_RSP * rsp = (DR_CONTROL_RSP *)NULL; + rsp = &rsps.control_rsp; + construct_DR_CONTROL_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + rsp->DeviceIoReply.Header.out = &send_RDPDR_HEADER; + rsp->DeviceIoReply.out = &send_DR_DEVICE_IOCOMPLETION; + rsp->out = &send_DR_CONTROL_RSP; + in_uint32_le(ls, rsp->OutputBufferLength); + if (rsp->OutputBufferLength > 0) { + rsp->OutputBuffer = (BYTE *)g_malloc(sizeof(BYTE) * rsp->OutputBufferLength, 1); + in_uint8a(ls, rsp->OutputBuffer, rsp->OutputBufferLength); + } + send_DR_CONTROL_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + // g_hexdump_file("/tmp/taskq_port_ioctl_rsp.hexdump", u->data, size); + MDBGLOG("redir","INFO\t[%s()]: (RDPPORT_IOCTL) reply (size = %d; rsp->OutputBufferLength = %d; rsp->DeviceIoReply.IoStatus = 0x%8.8x)",__func__,size,rsp->OutputBufferLength,rsp->DeviceIoReply.IoStatus.Value); + } + else if (rdp_opcode == RDPFS_GETXATTR) { + DR_DRIVE_QUERY_INFORMATION_RSP * rsp = (DR_DRIVE_QUERY_INFORMATION_RSP *)NULL; + rsp = &rsps.query_information_rsp; + construct_DR_DRIVE_QUERY_INFORMATION_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + send_DR_DRIVE_QUERY_INFORMATION_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_GETXATTR) reply",__func__); + } + else if (rdp_opcode == RDPFS_SETXATTR) { + } + else if (rdp_opcode == RDPFS_LISTXATTR) { + } + else if (rdp_opcode == RDPFS_REMOVEXATTR) { + } + else if (rdp_opcode == RDPFS_FSYNCDIR) { + DR_CONTROL_RSP * rsp = (DR_CONTROL_RSP *)NULL; + rsp = &rsps.control_rsp; + construct_DR_CONTROL_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + rsp->out(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_FSYNCDIR) reply",__func__); + } + else if (rdp_opcode == RDPFS_ACCESS) { + DR_CONTROL_RSP * rsp = (DR_CONTROL_RSP *)NULL; + rsp = &rsps.control_rsp; + construct_DR_CONTROL_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + send_DR_CONTROL_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_ACCESS) reply",__func__); + } + else if (rdp_opcode == RDPFS_FTRUNCATE) { + DR_DRIVE_SET_INFORMATION_RSP * rsp = (DR_DRIVE_SET_INFORMATION_RSP *)NULL; + rsp = &rsps.set_information_rsp; + construct_DR_DRIVE_SET_INFORMATION_RSP(rsp); + g_memcpy(&(rsp->DeviceIoReply), &ioc, sizeof(DR_DEVICE_IOCOMPLETION)); + in_uint32_le(ls, rsp->Length); + send_DR_DRIVE_SET_INFORMATION_RSP(rsp, u); + s_mark_end(u); + size = u->end - u->data; + MDBGLOG("redir","INFO\t[%s()]: (RDPFS_FTRUNCATE) reply",__func__); + } + else if (rdp_opcode == RDPFS_END || rdp_opcode == RDPPORT_END) { + MDBGLOG("redir","INFO\t[%s()]: (RDP_END) reply",__func__); + } + else if (rdp_opcode == RDPFS_DESTROY || rdp_opcode == RDPPORT_DESTROY) { + MDBGLOG("redir","INFO\t[%s()]: (RDP_DESTROY) reply",__func__); + } + else { + MDBGLOG("redir","ERROR\t[%s()]: unrecognized opcode \"0x%8.8x\"",__func__,rdp_opcode); + suppress = 1; + } + + if (!suppress) { + int devid = 0; + struct trans * ccon = (struct trans *)NULL; + devid = get_device_index(ioc.DeviceId); + if (fhandle == 0) { + fhandle = g_callbacks[opid].FileId; + } + if (uniqid == 0) { + uniqid = g_callbacks[opid].uniqid; + } + TC_MUTEX_LOCK(mutex_client_devicelist); + if (is_filesystem(devid)) { + MDBGLOG("redir","INFO\t[%s()]: is_filesystem() = true",__func__); + ccon = ((rdpfs *)(g_client_devicelist->DeviceList[devidx]->item))->ccon; + } + else if (is_port(devid)) { + MDBGLOG("redir","INFO\t[%s()]: is_port() = true",__func__); + ccon = ((rdpport_t *)(g_client_devicelist->DeviceList[devidx]->item))->ccon; + } + else if (is_printer(devid)) { + MDBGLOG("redir","INFO\t[%s()]: is_printer() = true",__func__); + ccon = ((rdpprint *)(g_client_devicelist->DeviceList[devidx]->item))->ccon; + } + else if (is_smartcard(devid)) { + MDBGLOG("redir","INFO\t[%s()]: is_smartcard() = true",__func__); + ccon = ((rdpsc *)(g_client_devicelist->DeviceList[devidx]->item))->ccon; + } + if (ccon != NULL) { + uint32_t * p_crc32 = (uint32_t *)NULL; + char * p = (char *)NULL; + magic = RDP_PACKET_MAGIC; + crc32 = Crc32_ComputeBuf((uint32_t)0, (void *)(u->data), (size_t)(u->p - u->data)); + t = trans_get_out_s(ccon, MAX_STREAM); + rdp_opcode |= RDP_REPLY; + if (device_id == 0) { + device_id = ioc.DeviceId; + } + MDBGLOG("redir"," {} DeviceId = %d; device_id = %d; CompletionId = %d; IoStatus = 0x%8.8x; rdp_opcode = 0x%8.8x, fhandle = %d; uniqid = %d",ioc.DeviceId,device_id,ioc.CompletionId,ioc.IoStatus.Value,rdp_opcode,fhandle,uniqid); + out_uint32_le(t, magic); + out_uint32_le(t, rdp_opcode); + out_uint32_le(t, size); + out_uint32_le(t, device_id); + out_uint32_le(t, fhandle); + out_uint32_le(t, uniqid); + p_crc32 = (uint32_t *)s_get_pos(t); + out_uint32_le(t, crc32); + p = (char *)s_get_pos(t); + if (size > 0) { + out_uint8a(t, u->data, size); + } + s_mark_end(t); + if (p_crc32 != NULL && p != NULL) { + *p_crc32 = Crc32_ComputeBuf((uint32_t)0, (void *)p, (size_t)(t->end - p)); + } + MDBGLOG("redir","about to send reply..."); + trans_force_write(ccon); + MDBGLOG("redir","reply sent. (size = %d)",size); + TC_MUTEX_UNLOCK(mutex_client_devicelist); + } + + if (send_partial < 1) { + g_memset(&(g_callbacks[opid]),0,sizeof(callback)); + } + } + TC_MUTEX_UNLOCK(mutex_cb); + } + break; + case PAKID_CORE_CLIENT_CAPABILITY: + MDBGLOG("redir"," - hdr->PacketId = 0x%8.8x (PAKID_CORE_CLIENT_CAPABILITY)",hdr->PacketId); + rv = rdpdr_process_CLIENT_CAPABILITY(ls); + break; + case PAKID_CORE_DEVICELIST_REMOVE: + MDBGLOG("redir"," - hdr->PacketId = 0x%8.8x (PAKID_CORE_DEVICELIST_REMOVE)",hdr->PacketId); + rv = rdpdr_process_DEVICELIST_REMOVE(ls); + break; + default: + MDBGLOG("redir", "\n !!! [%s()]: unknown hdr->PacketId[CORE] = 0x%8.8x\n", __func__, hdr->PacketId); + break; + } + } + else if (hdr->Component == RDPDR_CTYP_PRN) { + switch (hdr->PacketId) { + case PAKID_PRN_CACHE_DATA: + MDBGLOG("redir"," - hdr->PacketId = 0x%8.8x (PAKID_PRN_CACHE_DATA)",hdr->PacketId); + // rv = rdpdr_process_PRN_CACHE_DATA(ls); + break; + case PAKID_PRN_USING_XPS: + MDBGLOG("redir"," - hdr->PacketId = 0x%8.8x (PAKID_PRN_USING_XPS)",hdr->PacketId); + // rv = rdpdr_process_PRN_USING_XPS(ls); + break; + default: + MDBGLOG("redir", "\n !!! INFO\t[%s()]: unknown hdr->PacketId[PRN] = 0x%8.8x\n", __func__, hdr->PacketId); + break; + } + } + + } + + return rv; } /*****************************************************************************/ int APP_CC -dev_redir_get_wait_objs(tbus* objs, int* count, int* timeout) -{ - return 0; +rdpdr_get_wait_objs(tbus * objs, int * count, int * timeout) { + int rv = 0; + int lcount = 0; + int idx = 0; + + // MDBGLOG("redir","INFO\t[%s()]: called [%d, %d]", __func__, g_getpid(), g_gettid()); + + if ((g_rdpdr_up == 0) || (objs == 0) || (count == 0) || g_is_child > 0) + { + } + else if (g_rdpdr_wait_obj > -1) { + lcount = *count; + objs[lcount] = g_rdpdr_wait_obj; + lcount++; + *count = lcount; + TC_MUTEX_LOCK(mutex_client_devicelist); + if (g_client_devicelist != NULL && g_client_devicelist->DeviceCount > 0) + for (idx=0; idx < g_client_devicelist->DeviceCount; idx++) { + if (g_client_devicelist->DeviceList[idx] != NULL && g_client_devicelist->DeviceList[idx]->item != NULL) { + int sck = -1; + if (is_filesystem(idx) && ((rdpfs *)(g_client_devicelist->DeviceList[idx]->item))->ccon != NULL && ((rdpfs *)(g_client_devicelist->DeviceList[idx]->item))->ccon->sck > 0) { + sck = ((rdpfs *)(g_client_devicelist->DeviceList[idx]->item))->ccon->sck; + // MDBGLOG("redir","INFO\t[%s()]: filesystem (sck = %d)",__func__,sck); + } + else if (is_port(idx) && ((rdpport_t *)(g_client_devicelist->DeviceList[idx]->item))->ccon != NULL && ((rdpport_t *)(g_client_devicelist->DeviceList[idx]->item))->ccon->sck > 0) { + sck = ((rdpport_t *)(g_client_devicelist->DeviceList[idx]->item))->ccon->sck; + // MDBGLOG("redir","INFO\t[%s()]: port (sck = %d)",__func__,sck); + } + else if (is_printer(idx) && ((rdpprint *)(g_client_devicelist->DeviceList[idx]->item))->ccon != NULL && ((rdpprint *)(g_client_devicelist->DeviceList[idx]->item))->ccon->sck > 0) { + sck = ((rdpprint *)(g_client_devicelist->DeviceList[idx]->item))->ccon->sck; + // MDBGLOG("redir","INFO\t[%s()]: printer (sck = %d)",__func__,sck); + } + else if (is_smartcard(idx) && ((rdpsc *)(g_client_devicelist->DeviceList[idx]->item))->ccon != NULL && ((rdpsc *)(g_client_devicelist->DeviceList[idx]->item))->ccon->sck > 0) { + sck = ((rdpsc *)(g_client_devicelist->DeviceList[idx]->item))->ccon->sck; + // MDBGLOG("redir","INFO\t[%s()]: smartcard (sck = %d)",__func__,sck); + } + else { + // MDBGLOG("redir","ERROR\t[%s()]: unrecognized origin",__func__); + } + if (sck > 0) { + lcount = *count; + objs[lcount] = sck; + lcount++; + *count = lcount; + } + } + } + TC_MUTEX_UNLOCK(mutex_client_devicelist); + } + + // MDBGLOG("redir","INFO\t[%s()]: done (lcount = %d).", __func__, lcount); + return rv; } /*****************************************************************************/ int APP_CC -dev_redir_check_wait_objs(void) -{ - return 0; +rdpdr_check_wait_objs(void) { + int rv = 0; + int idx = 0; + + //MDBGLOG("redir","INFO\t[%s()]: called [%d, %d]", __func__, g_getpid(), g_gettid()); + + if (!g_rdpdr_up || g_is_child > 0) { + rv = 0; + } + else { + TC_MUTEX_LOCK(mutex_client_devicelist); + if (g_is_wait_obj_set(g_rdpdr_wait_obj)) { + // MDBGLOG("redir","INFO\t[%s()]: g_rdpdr_wait_obj = %d [SET]",__func__,g_rdpdr_wait_obj); + } + else if (g_client_devicelist != NULL && g_client_devicelist->DeviceCount > 0) + for (idx = 0; idx < g_client_devicelist->DeviceCount; idx++) { + if (g_client_devicelist->DeviceList[idx] == NULL || g_client_devicelist->DeviceList[idx]->item == NULL) { + // MDBGLOG("redir","ERROR\t[%s()]: NULL pointer (idx = %d)",__func__,idx); + } + else { + struct trans * ccon = (struct trans *)NULL; + if (is_filesystem(idx) && ((rdpfs *)(g_client_devicelist->DeviceList[idx]->item))->ccon != NULL && ((rdpfs *)(g_client_devicelist->DeviceList[idx]->item))->ccon->sck > 0) { + // MDBGLOG("redir","INFO\t[%s()]: setting ccon for filesystem (idx = %d)",__func__,idx); + ccon = ((rdpfs *)(g_client_devicelist->DeviceList[idx]->item))->ccon; + } + else if (is_port(idx) && ((rdpport_t *)(g_client_devicelist->DeviceList[idx]->item))->ccon != NULL && ((rdpport_t *)(g_client_devicelist->DeviceList[idx]->item))->ccon->sck > 0) { + // MDBGLOG("redir","INFO\t[%s()]: setting ccon for port (idx = %d)",__func__,idx); + ccon = ((rdpport_t *)(g_client_devicelist->DeviceList[idx]->item))->ccon; + } + else if (is_printer(idx) && ((rdpprint *)(g_client_devicelist->DeviceList[idx]->item))->ccon != NULL && ((rdpprint *)(g_client_devicelist->DeviceList[idx]->item))->ccon->sck > 0) { + // MDBGLOG("redir","INFO\t[%s()]: setting ccon for printer",__func__); + ccon = ((rdpprint *)(g_client_devicelist->DeviceList[idx]->item))->ccon; + } + else if (is_smartcard(idx) && ((rdpsc *)(g_client_devicelist->DeviceList[idx]->item))->ccon != NULL && ((rdpsc *)(g_client_devicelist->DeviceList[idx]->item))->ccon->sck > 0) { + // MDBGLOG("redir","INFO\t[%s()]: setting ccon for smartcard",__func__); + ccon = ((rdpsc *)(g_client_devicelist->DeviceList[idx]->item))->ccon; + } + else { + // MDBGLOG("redir","ERROR\t[%s()]: unrecognized origin",__func__); + } + /* handle any inbound replies from the child: */ + if (ccon != NULL && trans_check_wait_objs(ccon) != 0) { + // MDBGLOG("redir","ERROR\t[%s()]: trans_check_wait_objs(ccon) != 0",__func__); + rv = -1; + } + } + } + TC_MUTEX_UNLOCK(mutex_client_devicelist); + } + // MDBGLOG("redir","INFO\t[%s()]: done (rv = %d).", __func__, rv); + return rv; +} + +/*****************************************************************************/ +static int APP_CC +rdpdr_process_format_announce(struct stream * ls, int a, int b) { + int rv = 0; + return rv; +} + +/*****************************************************************************/ +static int APP_CC +rdpdr_process_format_ack(struct stream * ls, int a, int b) { + int rv = 0; + return rv; +} + +/*****************************************************************************/ +static int APP_CC +rdpdr_process_data_request(struct stream * ls, int a, int b) { + int rv = 0; + return rv; +} + +/*****************************************************************************/ +static int APP_CC +rdpdr_process_data_response(struct stream * ls, int a, int b) { + int rv = 0; + return rv; +} + +/*****************************************************************************/ +static int APP_CC +rdpdr_process_DEVICE_REPLY(struct stream * s) { + int rv = 0; + MDBGLOG("redir","DEVICE_REPLY"); + return rv; +} + +/*****************************************************************************/ +static int APP_CC +rdpdr_process_DEVICE_IOREQUEST(struct stream * s) { + int rv = 0; + DR_DEVICE_IOREQUEST * pdu = (DR_DEVICE_IOREQUEST *)NULL; + + MDBGLOG("redir","DEVICE_IOREQUEST"); + + pdu = RDPDR_NEW(DR_DEVICE_IOREQUEST); + pdu->in(pdu, s); + + return rv; +} + +/*****************************************************************************/ +static int APP_CC +rdpdr_process_SERVER_CAPABILITY(struct stream * s) { + int rv = 0; + MDBGLOG("redir","SERVER_CAPABILITY"); + return rv; +} + +/*****************************************************************************/ +static int APP_CC +rdpdr_process_CLIENT_CAPABILITY(struct stream * s) { + int rv = 0; + MDBGLOG("redir","CLIENT_CAPABILITY"); + return rv; +} + +/*****************************************************************************/ +static int APP_CC +rdpdr_process_DEVICELIST_REMOVE(struct stream * s) { + int rv = 0; + MDBGLOG("redir","DEVICELIST_REMOVE"); + return rv; +} + +/*************************************************************************/ +/*************************************************************************/ + + +/**************** + send / receive + ****************/ + +/**************** + destructors + ****************/ + +/*****************************************************************************/ +static int APP_CC +rdpdr_process_DEVICELIST_ANNOUNCE(struct stream * s) { + int rv = 0; + int idx = 0; + int largc = 0; + int tmp = 0; + int tpos = 0; + int l_client_device_id = 0; + int child_finish = 0; + int l_fs = 0; + int l_port = 0; + int l_print = 0; + int l_sc = 0; + int g_pv[2] = { -1, -1 }; + int g_sv[2] = { -1, -1 }; + char ** largv = (char **)NULL; + char fname[512]; + + MDBGLOG("redir","INFO\t[%s()]: called [%d, %d]",__func__,g_getpid(),g_gettid()); + + g_memset(fname, 0, sizeof(char) * 512); + TC_MUTEX_LOCK(mutex_client_devicelist); + if (g_client_devicelist == NULL) { + g_client_devicelist = RDPDR_NEW(DR_DEVICELIST_ANNOUNCE); + } + if (g_client_devicelist->DeviceList == NULL) { + g_client_devicelist->DeviceList = (DEVICE_ANNOUNCE **)g_malloc(sizeof(size_t) * 96, 1); + } + TC_MUTEX_LOCK(mutex_fs_arr); + l_fs = 1; + if (g_fs_arr == NULL) { + g_fs_arr = (rdpfs **)g_malloc(sizeof(size_t) * 24, 1); + } + TC_MUTEX_LOCK(mutex_port_arr); + l_port = 1; + if (g_port_arr == NULL) { + g_port_arr = (rdpport_t **)g_malloc(sizeof(size_t) * 24, 1); + } + TC_MUTEX_LOCK(mutex_printer_arr); + l_print = 1; + if (g_printer_arr == NULL) { + g_printer_arr = (rdpprint **)g_malloc(sizeof(size_t) * 24, 1); + } + TC_MUTEX_LOCK(mutex_smartcard_arr); + l_sc = 1; + if (g_smartcard_arr == NULL) { + g_smartcard_arr = (rdpsc **)g_malloc(sizeof(size_t) * 24, 1); + } + in_uint32_le(s, tmp); +/*** !!!!! ugly development hack !!!! ***/ + //tmp = 1; + g_client_devicelist->DeviceCount += tmp; + for (idx = 0; idx < tmp; idx++) { +// tpos = g_client_devicelist->DeviceCount + idx; +// tpos = (g_client_devicelist->DeviceCount > 0) ? (g_client_devicelist->DeviceCount - 1) + idx : idx; + tpos = idx; + g_client_devicelist->DeviceList[tpos] = RDPDR_NEW(DEVICE_ANNOUNCE); + in_uint32_le(s, g_client_devicelist->DeviceList[tpos]->DeviceType); + in_uint32_le(s, g_client_devicelist->DeviceList[tpos]->DeviceId); + l_client_device_id = g_client_devicelist->DeviceList[tpos]->DeviceId; + in_uint8a(s, g_client_devicelist->DeviceList[tpos]->PreferredDosName, 8); + in_uint32_le(s, g_client_devicelist->DeviceList[tpos]->DeviceDataLength); + if (g_client_devicelist->DeviceList[tpos]->DeviceDataLength > 0) { + g_client_devicelist->DeviceList[tpos]->DeviceData = (BYTE *)g_malloc(sizeof(BYTE) * g_client_devicelist->DeviceList[tpos]->DeviceDataLength, 1); + in_uint8a(s, g_client_devicelist->DeviceList[tpos]->DeviceData, g_client_devicelist->DeviceList[tpos]->DeviceDataLength); + } + } + for (idx = 0; idx < tmp; idx++) { + MDBGLOG("redir","\n\t[[ DeviceDataLength = %d ]]\n",g_client_devicelist->DeviceList[tpos]->DeviceDataLength); + + tpos = idx; + l_client_device_id = g_client_devicelist->DeviceList[tpos]->DeviceId; + + /* if the device is a serial port, then handle it: */ + if ((g_client_devicelist->DeviceList[tpos]->DeviceType & RDPDR_DTYP_SERIAL) == g_client_devicelist->DeviceList[tpos]->DeviceType) { + char dbuf[512]; + char * dos_name = (char *)NULL; + g_memset(dbuf,0,sizeof(dbuf)); + dos_name = (g_client_devicelist->DeviceList[tpos]->PreferredDosName == NULL) ? g_strdup("NONE") : g_strdup(g_client_devicelist->DeviceList[tpos]->PreferredDosName); + g_port_arr[g_port_count] = (rdpport_t *)rdpport_main(SERIAL_PORT,g_port_count); + g_client_devicelist->DeviceList[tpos]->item = g_port_arr[g_port_count]; + if (g_port_arr[g_port_count] == NULL) { + continue; + } + g_port_arr[g_port_count]->device_id = g_client_devicelist->DeviceList[tpos]->DeviceId; + g_port_arr[g_port_count]->g_port_index = g_port_count; + g_port_arr[g_port_count]->g_device_index = tpos; + g_socketpair(g_pv); + g_tcp_set_non_blocking(g_pv[0]); + g_tcp_set_non_blocking(g_pv[1]); + g_port_arr[g_port_count]->parent_sck = g_pv[0]; + g_port_arr[g_port_count]->child_sck = g_pv[1]; + g_port_arr[g_port_count]->parent_pid = g_getpid(); + g_port_arr[g_port_count]->dos_name = dos_name; + g_port_count++; + MDBGLOG("redir"," ** serial port: \"%s\" (DeviceId = %d)",dos_name,l_client_device_id); + } + /* if the device is a parallel port, then handle it: */ + else if ((g_client_devicelist->DeviceList[tpos]->DeviceType & RDPDR_DTYP_PARALLEL) == RDPDR_DTYP_PARALLEL) { + char * dos_name = (char *)NULL; + dos_name = (g_client_devicelist->DeviceList[tpos]->PreferredDosName == NULL) ? g_strdup("NONE") : g_strdup(g_client_devicelist->DeviceList[tpos]->PreferredDosName); + g_port_arr[g_port_count] = (rdpport_t *)rdpport_main(PARALLEL_PORT,g_port_count); + g_client_devicelist->DeviceList[tpos]->item = g_port_arr[g_port_count]; + if (g_port_arr[g_port_count] == NULL) { + continue; + } + g_port_arr[g_port_count]->device_id = g_client_devicelist->DeviceList[tpos]->DeviceId; + g_port_arr[g_port_count]->g_port_index = g_port_count; + g_port_arr[g_port_count]->g_device_index = tpos; + g_socketpair(g_pv); + g_tcp_set_non_blocking(g_pv[0]); + g_tcp_set_non_blocking(g_pv[1]); + g_port_arr[g_port_count]->parent_sck = g_pv[0]; + g_port_arr[g_port_count]->child_sck = g_pv[1]; + g_port_arr[g_port_count]->parent_pid = g_getpid(); + l_child_pid = g_fork(); + if (l_child_pid == 0) { /* child process */ + l_child_pid = g_getpid(); + g_port_arr[g_port_count]->handler_pid = l_child_pid; + if (l_port > 0) { + TC_MUTEX_UNLOCK(mutex_port_arr); + l_port = 0; + } + handle_port(g_pv[1], g_port_arr[g_port_count]); + } + else { /* parent process */ + g_port_arr[g_port_count]->handler_pid = l_child_pid; + //g_tcp_close(g_port_arr[g_port_count]->fd); + + /* set up ccon as a transmission channel to the child */ + g_port_arr[g_port_count]->ccon = (struct trans *)trans_create((int)2, (int)MAX_STREAM, (int)MAX_STREAM); + g_port_arr[g_port_count]->ccon->trans_data_in = &port_data_in; + g_port_arr[g_port_count]->ccon->header_size = 28; + trans_attach(g_port_arr[g_port_count]->ccon, g_port_arr[g_port_count]->parent_sck); + g_port_arr[g_port_count]->ccon->sck = g_port_arr[g_port_count]->parent_sck; + g_port_arr[g_port_count]->ccon->callback_data = (rdpport_t *)(g_port_arr[g_port_count]); + MDBGLOG("redir"," --> g_pv[0] = %d", g_pv[0]); + } + g_port_count++; + MDBGLOG("redir"," ** parallel port: \"%s\" (DeviceId = %d)",dos_name,l_client_device_id); + } + /* if the device is a printer, then create a corresponding rdpprint and manage it: */ + else if ((g_client_devicelist->DeviceList[tpos]->DeviceType & RDPDR_DTYP_PRINT) == RDPDR_DTYP_PRINT) { + char * dos_name = (char *)NULL; + dos_name = g_strdup(g_client_devicelist->DeviceList[tpos]->PreferredDosName); + g_printer_arr[g_printer_count] = (rdpprint *)g_malloc(sizeof(rdpprint), 1); + g_client_devicelist->DeviceList[tpos]->item = g_printer_arr[g_printer_count]; + if (g_printer_arr[g_printer_count] == NULL) { + continue; + } + g_printer_arr[g_printer_count]->type = XPS_PRINTER; + g_printer_arr[g_printer_count]->device_id = g_client_devicelist->DeviceList[tpos]->DeviceId; + g_printer_arr[g_printer_count]->g_printer_index = tpos; + g_socketpair(g_pv); + g_tcp_set_non_blocking(g_pv[0]); + g_tcp_set_non_blocking(g_pv[1]); + g_printer_arr[g_printer_count]->parent_sck = g_pv[0]; + g_printer_arr[g_printer_count]->child_sck = g_pv[1]; + g_printer_arr[g_printer_count]->parent_pid = g_getpid(); + p_child_pid = g_fork(); + if (p_child_pid == 0) { /* child process */ + p_child_pid = g_getpid(); + g_printer_arr[g_printer_count]->handler_pid = p_child_pid; + if (l_print > 0) { + TC_MUTEX_UNLOCK(mutex_printer_arr); + l_print = 0; + } + handle_printer(g_pv[1], g_printer_arr[g_printer_count]); + } + else { /* parent process */ + g_printer_arr[g_printer_count]->handler_pid = p_child_pid; + //g_tcp_close(g_printer_arr[g_printer_count]->fd); + + /* set up ccon as a transmission channel to the child */ + g_printer_arr[g_printer_count]->ccon = (struct trans *)trans_create((int)2, (int)MAX_STREAM, (int)MAX_STREAM); + g_printer_arr[g_printer_count]->ccon->trans_data_in = &printer_data_in; + g_printer_arr[g_printer_count]->ccon->header_size = 28; + trans_attach(g_printer_arr[g_printer_count]->ccon, g_printer_arr[g_printer_count]->parent_sck); + g_printer_arr[g_printer_count]->ccon->sck = g_printer_arr[g_printer_count]->parent_sck; + g_printer_arr[g_printer_count]->ccon->callback_data = (rdpprint *)(g_printer_arr[g_printer_count]); + MDBGLOG("redir"," --> g_pv[0] = %d", g_pv[0]); + } + g_printer_count++; + MDBGLOG("redir"," ** printer: \"%s\" (DeviceId = %d)",dos_name,l_client_device_id); + } + /* if the device is a smartcard, then create a corresponding rdpsc and manage it: */ + else if ((g_client_devicelist->DeviceList[tpos]->DeviceType & RDPDR_DTYP_SMARTCARD) == RDPDR_DTYP_SMARTCARD) { + char * dos_name = (char *)NULL; + dos_name = g_strdup(g_client_devicelist->DeviceList[g_smartcard_count]->PreferredDosName); + g_smartcard_arr[g_smartcard_count] = (rdpsc *)g_malloc(sizeof(rdpsc), 1); + g_client_devicelist->DeviceList[tpos]->item = g_smartcard_arr[g_smartcard_count]; + if (g_smartcard_arr[g_smartcard_count] == NULL) { + continue; + } + g_smartcard_arr[g_smartcard_count]->device_id = g_client_devicelist->DeviceList[tpos]->DeviceId; + g_smartcard_arr[g_smartcard_count]->g_smartcard_index = g_smartcard_count; + g_smartcard_arr[g_smartcard_count]->g_device_index = tpos; + g_socketpair(g_pv); + g_tcp_set_non_blocking(g_pv[0]); + g_tcp_set_non_blocking(g_pv[1]); + g_smartcard_arr[g_smartcard_count]->parent_sck = g_pv[0]; + g_smartcard_arr[g_smartcard_count]->child_sck = g_pv[1]; + g_smartcard_arr[g_smartcard_count]->parent_pid = g_getpid(); + s_child_pid = g_fork(); + if (s_child_pid == 0) { /* child process */ + s_child_pid = g_getpid(); + g_smartcard_arr[g_smartcard_count]->handler_pid = s_child_pid; + if (l_sc > 0) { + TC_MUTEX_UNLOCK(mutex_smartcard_arr); + l_sc = 0; + } + handle_smartcard(g_pv[1], g_smartcard_arr[g_smartcard_count]); + } + else { /* parent process */ + g_smartcard_arr[g_smartcard_count]->handler_pid = s_child_pid; + + //g_tcp_close(g_smartcard_arr[g_smartcard_count]->fd); + + /* set up ccon as a transmission channel to the child */ + g_smartcard_arr[g_smartcard_count]->ccon = (struct trans *)trans_create((int)2, (int)MAX_STREAM, (int)MAX_STREAM); + g_smartcard_arr[g_smartcard_count]->ccon->trans_data_in = &smartcard_data_in; + g_smartcard_arr[g_smartcard_count]->ccon->header_size = 28; + trans_attach(g_smartcard_arr[g_smartcard_count]->ccon, g_smartcard_arr[g_smartcard_count]->parent_sck); + g_smartcard_arr[g_smartcard_count]->ccon->sck = g_smartcard_arr[g_smartcard_count]->parent_sck; + g_smartcard_arr[g_smartcard_count]->ccon->callback_data = (rdpsc *)(g_smartcard_arr[g_smartcard_count]); + MDBGLOG("redir"," --> g_pv[0] = %d", g_pv[0]); + } + } + /* if the device is a file system, then create a corresponding rdpfs and mount it: */ + else if ((g_client_devicelist->DeviceList[tpos]->DeviceType & RDPDR_DTYP_FILESYSTEM) == RDPDR_DTYP_FILESYSTEM) { + char * dos_name = (char *)NULL; + char * ncolon = (char *)NULL; + dos_name = g_client_devicelist->DeviceList[tpos]->PreferredDosName; + ncolon = g_strchr(g_client_devicelist->DeviceList[tpos]->PreferredDosName,':'); + if (ncolon != NULL) { + int tnum = 0; + tnum = (char *)ncolon - (char *)(g_client_devicelist->DeviceList[tpos]->PreferredDosName); + dos_name = (char *)g_malloc(sizeof(char)*tnum, 1); + g_strncpy(dos_name,g_client_devicelist->DeviceList[tpos]->PreferredDosName,tnum); + } + if (!g_directory_exist(g_fbase)) { + if (!g_directory_exist("/media")) { + MDBGLOG("parent","ERROR [rdpdr_process_DEVICELIST_ANNOUNCE()]: mount directory \"/media\" does not exist; not mounting remote filesystem"); + } + else { + g_dir_create(g_fbase,0755); + } + } + g_snprintf(fname,511,"%s/%s",g_fbase,dos_name); + largc = 1; + largv = (char **)g_malloc(sizeof(size_t) * largc, 1); + largv[0] = g_strdup(fname); + largv[1] = (char *)NULL; + MDBGLOG("redir","largc = %d; largv[0] = %s; largv[1] = %s",largc,largv[0],largv[1]); + + g_fs_arr[g_fs_count] = (rdpfs *)rdpfs_main(largc, largv, largv[0]); + g_client_devicelist->DeviceList[tpos]->item = g_fs_arr[g_fs_count]; + if (g_fs_arr[g_fs_count] == NULL) { + //TC_MUTEX_UNLOCK(g_handle_fs_mut); + continue; + } + g_fs_arr[g_fs_count]->g_fs_index = g_fs_count; + g_memset(fname, 0, sizeof(char) * 512); + if (largv[0] != NULL) { + //g_free(largv[0]); + } + if (largv != NULL) { + //g_free(largv); + } + + g_fs_arr[g_fs_count]->device_id = g_client_devicelist->DeviceList[tpos]->DeviceId; + g_fs_arr[g_fs_count]->g_fs_index = g_fs_count; + g_fs_arr[g_fs_count]->g_device_index = tpos; + g_socketpair(g_pv); + g_tcp_set_non_blocking(g_pv[0]); + g_tcp_set_non_blocking(g_pv[1]); + g_fs_arr[g_fs_count]->parent_sck = g_pv[0]; + g_fs_arr[g_fs_count]->child_sck = g_pv[1]; + g_fs_arr[g_fs_count]->parent_pid = g_getpid(); + g_fs_count++; + //MDBGLOG("redir","INFO\t[%s()]: ** file system: \"%s\" (DeviceId = %d, l_client_device_id = %d)",__func__,dos_name,g_fs_arr[g_fs_count]->device_id,l_client_device_id); + } + } + + if (l_sc > 0) { + TC_MUTEX_UNLOCK(mutex_smartcard_arr); + l_sc = 0; + } + if (l_print > 0) { + TC_MUTEX_UNLOCK(mutex_printer_arr); + l_print = 0; + } + + for (idx = 0; idx < g_port_count; idx++) { + int l_port_count = idx; + l_child_pid = g_fork(); + if (l_child_pid == 0) { /* child process */ + g_is_child = 1; + l_child_pid = g_getpid(); + g_port_arr[l_port_count]->handler_pid = l_child_pid; + g_port_arr[l_port_count]->child_pid = l_child_pid; + //g_tcp_close(g_port_arr[l_port_count]->child_sck); + if (l_port > 0) { + TC_MUTEX_UNLOCK(mutex_port_arr); + l_port = 0; + } + handle_port(g_port_arr[l_port_count]->child_sck, g_port_arr[l_port_count]); + } + else { /* parent process */ + g_port_arr[l_port_count]->handler_pid = l_child_pid; + g_port_arr[l_port_count]->child_pid = l_child_pid; + //g_tcp_close(g_port_arr[l_port_count]->parent_sck); + + /* set up ccon as a transmission channel to the child */ + g_port_arr[l_port_count]->ccon = (struct trans *)trans_create((int)2, (int)MAX_STREAM, (int)MAX_STREAM); + g_port_arr[l_port_count]->ccon->trans_data_in = &port_data_in; + g_port_arr[l_port_count]->ccon->header_size = 28; + trans_attach(g_port_arr[l_port_count]->ccon, g_port_arr[l_port_count]->parent_sck); + g_port_arr[l_port_count]->ccon->sck = g_port_arr[l_port_count]->parent_sck; + g_port_arr[l_port_count]->ccon->callback_data = (rdpport_t *)(g_port_arr[l_port_count]); + //MDBGLOG("redir"," --> g_pv[0] = %d", g_pv[0]); + MDBGLOG("redir","INFO\t[%s()]: --> g_port_arr[l_port_count]->ccon->sck = %d", __func__, g_port_arr[l_port_count]->ccon->sck); + } + } + + if (l_port > 0) { + TC_MUTEX_UNLOCK(mutex_port_arr); + l_port = 0; + } + + MDBGLOG("redir","INFO\t[%s()]: about to lock ... [%d, %d]",__func__,g_getpid(),g_gettid()); + //TC_MUTEX_LOCK(g_handle_fs_mut); + for (idx = 0; idx < g_fs_count; idx++) { + int l_fs_count = idx; + l_child_pid = g_fork(); + if (l_child_pid == 0) { // child process + MDBGLOG("redir","INFO\t[%s()]: idx = %d [%d, %d]",__func__,idx,g_getpid(),g_gettid()); + g_is_child = 1; + break; + } + else { // parent process + MDBGLOG("redir","INFO\t[%s()]: idx = %d [%d, %d]",__func__,idx,g_getpid(),g_gettid()); + /* set up ccon as a transmission channel to the child */ + g_fs_arr[l_fs_count]->handler_pid = l_child_pid; + g_fs_arr[l_fs_count]->child_pid = l_child_pid; + } + } + if (g_is_child > 0) { + int l_fs_count = idx; + if (g_is_child > 0) { + int j = 0; + l_child_pid = g_getpid(); + g_fs_arr[l_fs_count]->handler_pid = l_child_pid; + g_fs_arr[l_fs_count]->child_pid = l_child_pid; + MDBGLOG("redir", "INFO\t[%s()]: child process (filesystem: parent_pid = %d, parent_sck = %d, child_pid = %d, child_sck = %d)", __func__, g_fs_arr[l_fs_count]->parent_pid, g_fs_arr[l_fs_count]->parent_sck, g_fs_arr[l_fs_count]->child_pid, g_fs_arr[l_fs_count]->child_sck); +// for (j = 0; j < l_fs_count; j++) { + for (j = 0; j < g_fs_count; j++) if (g_fs_arr[j] != NULL) { + if (g_fs_arr[j]->ccon != NULL && g_fs_arr[j]->ccon->sck) { + //g_file_close(g_fs_arr[j]->ccon->sck); + } + //g_fs_arr[j]->initialized = 0; + trans_detach(g_fs_arr[j]->ccon); + //trans_delete(g_fs_arr[j]->ccon); + if (g_fs_arr[j] != NULL && g_fs_arr[j]->ccon != NULL) { + //g_free(g_fs_arr[j]->ccon); + //g_fs_arr[j]->ccon = NULL; + } + } + { + int tsck = g_fs_arr[l_fs_count]->child_sck; + rdpfs * tfs = g_fs_arr[l_fs_count]; + rdpfs ** tfs_arr = g_fs_arr; + tc_p pmut = mutex_fs_arr; + if (l_fs > 0) { + TC_MUTEX_UNLOCK(mutex_fs_arr); + l_fs = 0; + } + handle_filesystem(tsck, tfs, tfs_arr, pmut); + } + child_finish = 1; + //break; + //goto finish; + } + else { /* parent process */ + } + } + else { + for (idx = 0; idx < g_fs_count; idx++) { + int l_fs_count = idx; + MDBGLOG("redir","INFO\t[%s()]: (round2) idx = %d [%d, %d]",__func__,idx,g_getpid(),g_gettid()); + g_fs_arr[l_fs_count]->ccon = (struct trans *)trans_create((int)2, (int)MAX_STREAM, (int)MAX_STREAM); + g_fs_arr[l_fs_count]->ccon->trans_data_in = &filesystem_data_in; + g_fs_arr[l_fs_count]->ccon->header_size = 28; + trans_attach(g_fs_arr[l_fs_count]->ccon, g_fs_arr[l_fs_count]->parent_sck); + g_fs_arr[l_fs_count]->ccon->sck = g_fs_arr[l_fs_count]->parent_sck; + g_fs_arr[l_fs_count]->ccon->callback_data = (rdpfs *)(g_fs_arr[l_fs_count]); + } + } + if (g_fs_count > 0 && child_finish < 1) { + g_handle_filesystem_called = 1; + } + if (child_finish < 1) { + //TC_MUTEX_UNLOCK(g_handle_fs_mut); + } + + if (l_fs > 0) { + TC_MUTEX_UNLOCK(mutex_fs_arr); + l_fs = 0; + } + + TC_MUTEX_UNLOCK(mutex_client_devicelist); + + //MDBGLOG("redir","rdpdr_process_DEVICELIST_ANNOUNCE(): done (DeviceType = 0x%8.8x; DeviceId = 0x%8.8x; PreferredDosName = %s).",g_client_devicelist->DeviceList[tpos]->DeviceType,g_client_devicelist->DeviceList[tpos]->DeviceId,g_client_devicelist->DeviceList[tpos]->PreferredDosName); + return rv; +} + + +/*****************************************************************************/ +static char * APP_CC ucs2ascii(const uint8_t * ucs) { + char * ascii = NULL; + char el = -1; + int idx = 0; + + ascii = g_malloc(sizeof(char)*512,1); + for (idx = 0; (idx < 511) && (el != 0); idx++) { + el = ucs[(idx * 2)]; + ascii[idx] = el; + } + + return ascii; +} + +/*****************************************************************************/ +static int APP_CC +port_data_in(struct trans * trans) { + int rv = 0; + struct stream * s = (struct stream *)NULL; + char odata[MAX_STREAM]; + struct stream os; + char qdata[MAX_STREAM]; + struct stream qs; + char tdata[MAX_STREAM]; + struct stream ts; + struct stream * r = (struct stream *)NULL; + struct stream * q = (struct stream *)NULL; + struct stream * l = (struct stream *)NULL; + callback * cb = (callback *)NULL; + int fpath_length = 0; + int rdpport_opcode = 0; + int size = 0; + int error = 0; + int idx = 0; + int opid = 0; + int fhandle = 0; + int uniqid = 0; + uint32_t tflags = 0x00000000; + uint32_t toptions = 0x00000000; + uint32_t tshare = 0x00000000; + uint32_t tsize = 0x00000000; + uint64_t toffset = 0x0000000000000000; + uint64_t tchangetime = 0x0000000000000000; + uint64_t tactime = 0x0000000000000000; + uint64_t tmodtime = 0x0000000000000000; + uint32_t tattributes = 0x0000000000000000; + uint32_t treserved = 0x0000000000000000; + uint32_t tinputbufferlength = 0; + uint32_t toutputbufferlength = 0; + uint32_t tcmd = 0; + uint32_t calc_crc32 = 0x00000000; + uint32_t crc32 = 0x00000000; + uint32_t magic = 0x00000000; + uint32_t device_id = 0x00000000; + BYTE * tbuffer = (BYTE *)NULL; + BYTE * toutbuffer = (BYTE *)NULL; + void * pdu = (void *)NULL; + BYTE * buf = (BYTE *)NULL; + char * cbuf = (char *)NULL; + char * tpos = NULL; + char * qpos = NULL; + char tchar = 0; + + MDBGLOG("redir","port_data_in(): called"); + + if (trans == 0) { + return 0; + } + + g_memset((char *)tdata,0,sizeof(char)*MAX_STREAM); + g_memset(&ts,0,sizeof(struct stream)); + ts.data = (char *)tdata; + ts.p = ts.data; + ts.end = ts.data; + ts.size = MAX_STREAM; + r = &ts; + g_memset((char *)qdata,0,sizeof(char)*MAX_STREAM); + g_memset(&qs,0,sizeof(struct stream)); + qs.data = (char *)qdata; + qs.p = qs.data; + qs.end = qs.data; + qs.size = MAX_STREAM; + q = &qs; + g_memset((char *)odata,0,sizeof(char)*MAX_STREAM); + g_memset(&os,0,sizeof(struct stream)); + os.data = (char *)odata; + os.p = os.data; + os.end = os.data; + os.size = MAX_STREAM; + l = &os; + + s = (struct stream *)trans_get_in_s(trans); + g_memcpy(l->data,s->data,s->size); + l->size = s->size; + if ((s->p - s->data) > 0) { + l->p += (s->p - s->data); + } + if ((s->end - s->data) > 0) { + l->end = l->data + (s->end - s->data); + } + g_memcpy(q->data,s->data,s->size); + q->size = s->size; + if ((s->p - s->data) > 0) { + q->p += (s->p - s->data); + } + if ((s->end - s->data) > 0) { + q->end = q->data + (s->end - s->data); + } + // g_hexdump_file("/tmp/taskq_parent_pronto.hexdump",q->data,q->size); + in_uint32_le(q, magic); + in_uint32_le(q, rdpport_opcode); + in_uint32_le(q, size); + in_uint32_le(q, device_id); + in_uint32_le(q, fhandle); + in_uint32_le(q, uniqid); + in_uint32_le(q, crc32); + + if (size > 0) { + int tlen = size; + trans_force_read(trans, tlen); + s->p += 28; + calc_crc32 = Crc32_ComputeBuf(0, s->p, tlen); + MDBGLOG("redir", "INFO\t[%s()]: crc32 = 0x%8.8x, calc_crc32 = 0x%8.8x", __func__, crc32, calc_crc32); + if ((rdpport_opcode & RDPPORT_READ) == rdpport_opcode) { + in_uint32_le(s, tsize); + in_uint64_le(s, toffset); + tlen -= 12; + } + else if ((rdpport_opcode & RDPPORT_WRITE) == rdpport_opcode) { + in_uint32_le(s, tsize); + in_uint64_le(s, toffset); + in_uint8(s, tchar); + tlen -= (12 + tsize); +// tlen -= 12; + } + else if ((rdpport_opcode & RDPPORT_IOCTL) == rdpport_opcode && rdpport_opcode != 0x00000000) { + in_uint32_le(s, tcmd); + in_uint32_le(s, tinputbufferlength); + in_uint32_le(s, toutputbufferlength); + if (tinputbufferlength > 0) { + tbuffer = (BYTE *)g_malloc(sizeof(BYTE) * tinputbufferlength, 1); + in_uint8a(s, tbuffer, tinputbufferlength); + } + tlen -= (12 + tinputbufferlength); + } + else if ((rdpport_opcode & RDPPORT_OPEN) == rdpport_opcode) { + in_uint32_le(s, tflags); + in_uint32_le(s, tshare); + in_uint32_le(s, toptions); + in_uint32_le(s, tattributes); + tlen -= (16 + tsize); + } + if (tlen > 0) { + cbuf = (char *)g_malloc(sizeof(char) * tlen, 1); + buf = (BYTE *)g_malloc(sizeof(BYTE) * tlen, 1); + in_uint8a(s, (char *)cbuf, tlen); + g_memcpy((char *)buf,cbuf,tlen); + } + } + + MDBGLOG("redir","\n\n ** port_data_in(): rdpport_opcode = %8.8x; size = %d; uniqid = %d; fhandle = %d; buf = \"%s\"; tflags = 0x%8.8x; tsize = %d; toffset = %lu\n",rdpport_opcode,size,uniqid,fhandle,(char *)buf,tflags,tsize,toffset); + + if (error == 0) { + int found = 0; + TC_MUTEX_LOCK(mutex_cb); + for (opid = 4; opid < MAX_PENDING; opid++) { + if (g_callbacks[opid].opid < 1) { + found = 1; + break; + } + } + if (found > 0) { + g_memset((callback *)(&(g_callbacks[opid])), 0, sizeof(callback)); + g_callbacks[opid].opid = opid; + g_callbacks[opid].type = 1; + g_callbacks[opid].port = g_port_arr[0]; + g_callbacks[opid].fd = g_port_arr[0]->parent_sck; + g_callbacks[opid].opcode = rdpport_opcode; + g_callbacks[opid].CompletionId = opid; + g_callbacks[opid].trans = g_port_arr[0]->ccon; + g_callbacks[opid].uniqid = uniqid; + g_callbacks[opid].FileId = fhandle; + g_callbacks[opid].setData = &cb_set_data; + g_callbacks[opid].call = &cb_call; + g_callbacks[opid].callData = &cb_call_data; + if (size > 0 && buf != NULL && g_strlen(buf) > 0) { + g_memcpy(g_callbacks[opid].fname,buf,(size > 511)?511:size); + } + cb = &(g_callbacks[opid]); + } + if (found < 1) { + MDBGLOG("redir","ERROR [port_data_in()]: unable to allocate callback slot (opcode = %8.8x; opid = %d)",rdpport_opcode,opid); + error = -1; + } + else if (cb == NULL) { + MDBGLOG("redir","ERROR [port_data_in()]: failed to assign callback to operation (opcode = %8.8x; opid = %d)",rdpport_opcode,opid); + error = -1; + } + else { + switch(rdpport_opcode) { + case RDPPORT_OPEN: + MDBGLOG("redir","INFO [port_data_in()]: opcode = RDPPORT_OPEN"); + { + DR_CREATE_REQ ioreq; + char fpath[512]; + BYTE wpath[1024]; + int cnt = 0; + char * iptr = NULL; + char * optr = NULL; + int inum = 0; + int onum = 0; + g_memset(&ioreq,0,sizeof(DR_CREATE_REQ)); + g_memset((char *)fpath,0,sizeof(char)*512); + g_memset((BYTE *)wpath,0,sizeof(BYTE)*1024); + fpath_length = g_strlen(buf) + 1; + + iptr = buf; + optr = wpath; + inum = fpath_length; + onum = 1024; + g_outstr(&optr,&onum,&iptr,&inum); + cnt = fpath_length * 2; + + pdu = (void *)(&ioreq); + construct_DR_CREATE_REQ(&ioreq); + if (trans->callback_data != NULL) { + ioreq.DeviceIoRequest.DeviceId = ((rdpport_t *)trans->callback_data)->device_id; + } + else if (g_port_arr != NULL && g_port_arr[0] != NULL) { + ioreq.DeviceIoRequest.DeviceId = g_port_arr[0]->device_id; + } + ioreq.DeviceIoRequest.CompletionId = opid; + ioreq.DeviceIoRequest.MajorFunction = IRP_MJ_CREATE; + ioreq.DeviceIoRequest.MinorFunction = 0x00000000; + ioreq.CreateDisposition = FILE_OPEN; + ioreq.CreateOptions = toptions; + ioreq.DesiredAccess = tflags; + ioreq.SharedAccess = tshare; + ioreq.FileAttributes = tattributes; + ioreq.PathLength = 0; + send_DR_CREATE_REQ(&ioreq, r); + MDBGLOG("redir"," ^^ (RDPPORT_OPEN) FileId = %d",ioreq.DeviceIoRequest.FileId); + } + break; + case RDPPORT_CLOSE: + MDBGLOG("redir","INFO [port_data_in()]: opcode = RDPPORT_CLOSE"); + { + DR_CLOSE_REQ ioreq; + g_memset(&ioreq,0,sizeof(DR_CLOSE_REQ)); + construct_DR_CLOSE_REQ(&ioreq); + ioreq.DeviceIoRequest.MajorFunction = IRP_MJ_CLOSE; + TC_MUTEX_LOCK(mutex_client_devicelist); + TC_MUTEX_LOCK(mutex_port_arr); + if (g_client_devicelist != NULL && g_client_devicelist->DeviceList != NULL && g_client_devicelist->DeviceList[0] != NULL) { + ioreq.DeviceIoRequest.DeviceId = g_client_devicelist->DeviceList[0]->DeviceId; + } + else if (g_port_arr != NULL && g_port_arr[0] != NULL) { + ioreq.DeviceIoRequest.DeviceId = g_port_arr[0]->device_id; + } + TC_MUTEX_UNLOCK(mutex_port_arr); + TC_MUTEX_UNLOCK(mutex_client_devicelist); + ioreq.DeviceIoRequest.FileId = fhandle; + ioreq.DeviceIoRequest.CompletionId = opid; + cb->FileId = fhandle; + send_DR_CLOSE_REQ(&ioreq, r); + MDBGLOG("redir","port_data_in(): [RDPPORT_CLOSE] request sent (FileId = %d)",ioreq.DeviceIoRequest.FileId); + } + break; + case RDPPORT_READ: + MDBGLOG("redir","INFO [port_data_in()]: opcode = RDPPORT_READ"); + { + DR_READ_REQ ioreq; + construct_DR_READ_REQ(&ioreq); + ioreq.DeviceIoRequest.MajorFunction = IRP_MJ_READ; + if (trans->callback_data != NULL) { + ioreq.DeviceIoRequest.DeviceId = ((rdpport_t *)trans->callback_data)->device_id; + } + else if (g_port_arr != NULL && g_port_arr[0] != NULL) { + ioreq.DeviceIoRequest.DeviceId = g_port_arr[0]->device_id; + } + ioreq.DeviceIoRequest.CompletionId = opid; + ioreq.DeviceIoRequest.FileId = fhandle; + cb->opid = opid; + cb->FileId = fhandle; + ioreq.Length = tsize; + ioreq.Offset = toffset; + send_DR_READ_REQ(&ioreq, r); + MDBGLOG("redir"," ^^ (RDPFS_READ): ioreq.Length = %d; ioreq.Offset = %llu; tsize = %d; toffset = %llu; buf = \"%s\"; ioreq.DeviceIoRequest.DeviceId = %d; ioreq.DeviceIoRequest.FileId = %d; ioreq.DeviceIoRequest.MajorFunction = 0x%8.8x",ioreq.Length,ioreq.Offset,tsize,toffset,buf,ioreq.DeviceIoRequest.DeviceId,ioreq.DeviceIoRequest.FileId,ioreq.DeviceIoRequest.MajorFunction); + } + break; + case RDPPORT_WRITE: + //MDBGLOG("redir","INFO [port_data_in()]: opcode = RDPPORT_WRITE"); + { + DR_WRITE_REQ ioreq; + construct_DR_WRITE_REQ(&ioreq); + ioreq.DeviceIoRequest.MajorFunction = IRP_MJ_WRITE; + if (trans->callback_data != NULL) { + ioreq.DeviceIoRequest.DeviceId = ((rdpport_t *)trans->callback_data)->device_id; + } + else if (g_port_arr != NULL && g_port_arr[0] != NULL) { + ioreq.DeviceIoRequest.DeviceId = g_port_arr[0]->device_id; + } + ioreq.DeviceIoRequest.CompletionId = opid; + ioreq.DeviceIoRequest.FileId = fhandle; + ioreq.Length = tsize; + toffset = 0; + ioreq.Offset = toffset; + ioreq.WriteData = (BYTE *)g_malloc(sizeof(BYTE) * ioreq.Length, 1); + g_memcpy(ioreq.WriteData, &tchar, sizeof(char)); + + //MDBGLOG("redir"," ^^ (RDPPORT_WRITE): ioreq.WriteData = \"%s\"; ioreq.Length = %d; ioreq.Offset = %d",(unsigned char *)(&(ioreq.WriteData[0])),ioreq.Length,ioreq.Offset); + send_DR_WRITE_REQ(&ioreq, r); + } + break; + case RDPPORT_IOCTL: + MDBGLOG("redir","INFO [port_data_in()]: opcode = RDPPORT_IOCTL (fhandle = %d, tinputbufferlength = %d, toutputbufferlength = %d, tcmd = 0x%8.8x)", fhandle, tinputbufferlength, toutputbufferlength, tcmd); + { + DR_CONTROL_REQ ioctlreq; + construct_DR_CONTROL_REQ(&ioctlreq); + if (trans->callback_data != NULL) { + ioctlreq.DeviceIoRequest.DeviceId = ((rdpport_t *)trans->callback_data)->device_id; + } + else if (g_port_arr != NULL && g_port_arr[0] != NULL) { + ioctlreq.DeviceIoRequest.DeviceId = g_port_arr[0]->device_id; + } + ioctlreq.DeviceIoRequest.CompletionId = opid; + ioctlreq.DeviceIoRequest.FileId = fhandle; + ioctlreq.DeviceIoRequest.MajorFunction = IRP_MJ_DEVICE_CONTROL; + ioctlreq.DeviceIoRequest.MinorFunction = 0x00000000; + ioctlreq.InputBufferLength = tinputbufferlength; + ioctlreq.OutputBufferLength = toutputbufferlength; + ioctlreq.IoControlCode = tcmd; + if (tbuffer != NULL) { + ioctlreq.InputBuffer = tbuffer; + } + send_DR_CONTROL_REQ(&ioctlreq, r); + } + break; + case RDPPORT_INIT: + MDBGLOG("redir","INFO [port_data_in()]: opcode = RDPPORT_INIT"); + { + } + break; + case RDPPORT_DESTROY: + MDBGLOG("redir","INFO [port_data_in()]: opcode = RDPPORT_DESTROY"); + { + } + break; + default: + MDBGLOG("redir","ERROR [port_data_in()]: unrecognized opcode (0x%8.8x)",rdpport_opcode); + r = trans_get_out_s(trans, MAX_STREAM); + magic = RDP_PACKET_MAGIC; + crc32 = 0x00000000; + size = 0x00000000; + out_uint32_le(r, magic); + out_uint32_le(r, RDPPORT_ERROR); + out_uint32_le(r, size); + out_uint32_le(r, device_id); + out_uint32_le(r, fhandle); + out_uint32_le(r, uniqid); + out_uint32_le(r, crc32); + s_mark_end(r); + trans_force_write(trans); + r->end = r->data; + break; + } + /* send the assembled PDU to the RDP client: */ + //MDBGLOG("redir","[port_data_in()]: sending PDU to RDP channel..."); + s_mark_end(r); + size = r->end - r->data; + if (size > 0) { + TC_MUTEX_LOCK(mutex_out); + error = send_channel_data(g_rdpdr_chan_id, r->data, size); + TC_MUTEX_UNLOCK(mutex_out); + //MDBGLOG("redir","[port_data_in()]: sent. (error = %d; g_rdpdr_chan_id = %d)",error,g_rdpdr_chan_id); + //// g_hexdump_file("/tmp/taskq_port_pdu.hexdump", r->data, size); + if (rdpport_opcode == RDPPORT_READ) { + //// g_hexdump_file("/tmp/taskq_port_pdu_read.hexdump", r->data, size); + } + else if (rdpport_opcode == RDPPORT_WRITE) { + //// g_hexdump_file("/tmp/taskq_port_pdu_write.hexdump", r->data, size); + } + } + else { + MDBGLOG("redir","ERROR [port_data_in()]: output PDU is empty (size == 0)"); + } + } + TC_MUTEX_UNLOCK(mutex_cb); + } + return error; +} + +/*****************************************************************************/ +static int APP_CC +printer_data_in(struct trans * trans) { + int rv = 0; + struct stream * s = (struct stream *)NULL; + char odata[MAX_STREAM]; + struct stream os; + char qdata[MAX_STREAM]; + struct stream qs; + char tdata[MAX_STREAM]; + struct stream ts; + struct stream * r = (struct stream *)NULL; + struct stream * q = (struct stream *)NULL; + struct stream * l = (struct stream *)NULL; + callback * cb = (callback *)NULL; + int fpath_length = 0; + int rdpprint_opcode = 0; + int size = 0; + int error = 0; + int idx = 0; + int opid = 0; + int fhandle = 0; + int uniqid = 0; + uint32_t tflags = 0x00000000; + uint32_t toptions = 0x00000000; + uint32_t tshare = 0x00000000; + uint32_t tsize = 0x00000000; + uint64_t toffset = 0x0000000000000000; + uint64_t tchangetime = 0x0000000000000000; + uint64_t tactime = 0x0000000000000000; + uint64_t tmodtime = 0x0000000000000000; + uint32_t tattributes = 0x0000000000000000; + uint32_t treserved = 0x0000000000000000; + uint32_t tinputbufferlength = 0; + uint32_t toutputbufferlength = 0; + uint32_t tcmd = 0; + BYTE * tbuffer = (BYTE *)NULL; + void * pdu = (void *)NULL; + BYTE * buf = (BYTE *)NULL; + char * cbuf = (char *)NULL; + char * tpos = NULL; + char * qpos = NULL; + uint32_t crc32 = 0x00000000; + uint32_t calc_crc32 = 0x00000000; + uint32_t magic = 0x00000000; + uint32_t device_id = 0x00000000; + + MDBGLOG("redir","printer_data_in(): called"); + + if (trans == 0) { + return 0; + } + + g_memset((char *)tdata,0,sizeof(char)*MAX_STREAM); + g_memset(&ts,0,sizeof(struct stream)); + ts.data = (char *)tdata; + ts.p = ts.data; + ts.end = ts.data; + ts.size = MAX_STREAM; + r = &ts; + g_memset((char *)qdata,0,sizeof(char)*MAX_STREAM); + g_memset(&qs,0,sizeof(struct stream)); + qs.data = (char *)qdata; + qs.p = qs.data; + qs.end = qs.data; + qs.size = MAX_STREAM; + q = &qs; + g_memset((char *)odata,0,sizeof(char)*MAX_STREAM); + g_memset(&os,0,sizeof(struct stream)); + os.data = (char *)odata; + os.p = os.data; + os.end = os.data; + os.size = MAX_STREAM; + l = &os; + + s = (struct stream *)trans_get_in_s(trans); + g_memcpy(l->data,s->data,s->size); + l->size = s->size; + if ((s->p - s->data) > 0) { + l->p += (s->p - s->data); + } + if ((s->end - s->data) > 0) { + l->end = l->data + (s->end - s->data); + } + g_memcpy(q->data,s->data,s->size); + q->size = s->size; + if ((s->p - s->data) > 0) { + q->p += (s->p - s->data); + } + if ((s->end - s->data) > 0) { + q->end = q->data + (s->end - s->data); + } + // g_hexdump_file("/tmp/taskq_parent_pronto.hexdump",q->data,q->size); + in_uint32_le(q, magic); + in_uint32_le(q, rdpprint_opcode); + in_uint32_le(q, size); + in_uint32_le(q, device_id); + in_uint32_le(q, fhandle); + in_uint32_le(q, uniqid); + in_uint32_le(q, crc32); + + if (size > 0) { + int tlen = size; + trans_force_read(trans, tlen); + s->p += 28; + calc_crc32 = Crc32_ComputeBuf(0, s->p, tlen); + MDBGLOG("redir", "INFO\t[%s()]: crc32 = 0x%8.8x, calc_crc32 = 0x%8.8x", __func__, crc32, calc_crc32); + if ((rdpprint_opcode & RDPPRINT_READ) == RDPPRINT_READ) { + in_uint32_le(s, tsize); + in_uint64_le(s, toffset); + tlen -= 12; + } + else if ((rdpprint_opcode & RDPPRINT_WRITE) == RDPPRINT_WRITE) { + in_uint32_le(s, tsize); + in_uint64_le(s, toffset); + tlen -= (12 + tsize); + } + else if ((rdpprint_opcode & RDPPRINT_IOCTL) == RDPPRINT_IOCTL) { + in_uint32_le(s, tcmd); + in_uint32_le(s, tinputbufferlength); + toutputbufferlength = 4096; + if (tinputbufferlength > 0) { + tbuffer = (BYTE *)g_malloc(sizeof(BYTE) * tinputbufferlength, 1); + in_uint8a(s, tbuffer, tinputbufferlength); + } + tlen -= (8 + tinputbufferlength + tsize); + } + else if ((rdpprint_opcode & RDPPRINT_OPEN) == RDPPRINT_OPEN) { + in_uint32_le(s, tflags); + in_uint32_le(s, tshare); + in_uint32_le(s, toptions); + in_uint32_le(s, tattributes); + //tlen -= 8; + tlen -= (16 + tsize); + } + cbuf = (char *)g_malloc(sizeof(char) * tlen, 1); + buf = (BYTE *)g_malloc(sizeof(BYTE) * tlen, 1); + in_uint8a(s, (char *)cbuf, tlen); + g_memcpy((char *)buf,cbuf,tlen); + } + + MDBGLOG("redir","INFO\t[%s()]: ** printer_data_in(): rdpprint_opcode = %8.8x; size = %d; uniqid = %d; fhandle = %d; buf = \"%s\"; tflags = 0x%8.8x; tsize = %d; toffset = %lu",__func__,rdpprint_opcode,size,uniqid,fhandle,(char *)buf,tflags,tsize,toffset); + + if (error == 0) { + TC_MUTEX_LOCK(mutex_cb); + int found = 0; + for (opid = 4; opid < MAX_PENDING; opid++) { + if (g_callbacks[opid].opid < 1) { + found = 1; + break; + } + } + if (found > 0) { + g_memset((callback *)(&(g_callbacks[opid])), 0, sizeof(callback)); + g_callbacks[opid].opid = opid; + g_callbacks[opid].type = 1; + g_callbacks[opid].printer = g_printer_arr[0]; + g_callbacks[opid].fd = g_printer_arr[0]->parent_sck; + g_callbacks[opid].opcode = rdpprint_opcode; + g_callbacks[opid].CompletionId = opid; + g_callbacks[opid].trans = g_printer_arr[0]->ccon; + g_callbacks[opid].uniqid = uniqid; + g_callbacks[opid].FileId = fhandle; + g_callbacks[opid].setData = &cb_set_data; + g_callbacks[opid].call = &cb_call; + g_callbacks[opid].callData = &cb_call_data; + g_memcpy(g_callbacks[opid].fname,buf,(size > 511)?511:size); + cb = &(g_callbacks[opid]); + } + if (found < 1) { + MDBGLOG("redir","ERROR [printer_data_in()]: unable to allocate callback slot (opcode = %8.8x; opid = %d)",rdpprint_opcode,opid); + error = -1; + } + else if (cb == NULL) { + MDBGLOG("redir","ERROR [printer_data_in()]: failed to assign callback to operation (opcode = %8.8x; opid = %d)",rdpprint_opcode,opid); + error = -1; + } + else { + switch(rdpprint_opcode) { + default: + MDBGLOG("redir","ERROR [printer_data_in()]: unrecognized opcode (0x%8.8x)",rdpprint_opcode); + r = trans_get_out_s(trans, MAX_STREAM); + magic = RDP_PACKET_MAGIC; + crc32 = 0x00000000; + size = 0x00000000; + out_uint32_le(r, magic); + out_uint32_le(r, RDPPRINT_ERROR); + out_uint32_le(r, size); + out_uint32_le(r, device_id); + out_uint32_le(r, fhandle); + out_uint32_le(r, uniqid); + out_uint32_le(r, crc32); + s_mark_end(r); + trans_force_write(trans); + r->end = r->data; + break; + } + /* send the assembled PDU to the RDP client: */ + MDBGLOG("redir","[printer_data_in()]: sending PDU to RDP channel..."); + s_mark_end(r); + size = r->end - r->data; + if (size > 0) { + TC_MUTEX_LOCK(mutex_out); + error = send_channel_data(g_rdpdr_chan_id, r->data, size); + TC_MUTEX_UNLOCK(mutex_out); + MDBGLOG("redir","[printer_data_in()]: sent. (error = %d; g_rdpdr_chan_id = %d)",error,g_rdpdr_chan_id); + // g_hexdump_file("/tmp/taskq_printer_pdu.hexdump", r->data, size); + if (rdpprint_opcode == RDPPRINT_READ) { + // g_hexdump_file("/tmp/taskq_printer_pdu_read.hexdump", r->data, size); + } + } + else { + MDBGLOG("redir","ERROR [printer_data_in()]: output PDU is empty (size == 0)"); + } + } + TC_MUTEX_UNLOCK(mutex_cb); + } + return error; +} + +/*****************************************************************************/ +static int APP_CC +smartcard_data_in(struct trans * trans) { + int rv = 0; + struct stream * s = (struct stream *)NULL; + char odata[MAX_STREAM]; + struct stream os; + char qdata[MAX_STREAM]; + struct stream qs; + char tdata[MAX_STREAM]; + struct stream ts; + struct stream * r = (struct stream *)NULL; + struct stream * q = (struct stream *)NULL; + struct stream * l = (struct stream *)NULL; + callback * cb = (callback *)NULL; + int fpath_length = 0; + int rdpsc_opcode = 0; + int size = 0; + int error = 0; + int idx = 0; + int opid = 0; + int fhandle = 0; + int uniqid = 0; + uint32_t tflags = 0x00000000; + uint32_t toptions = 0x00000000; + uint32_t tshare = 0x00000000; + uint32_t tsize = 0x00000000; + uint64_t toffset = 0x0000000000000000; + uint64_t tchangetime = 0x0000000000000000; + uint64_t tactime = 0x0000000000000000; + uint64_t tmodtime = 0x0000000000000000; + uint32_t tattributes = 0x0000000000000000; + uint32_t treserved = 0x0000000000000000; + uint32_t tinputbufferlength = 0; + uint32_t toutputbufferlength = 0; + uint32_t tcmd = 0; + BYTE * tbuffer = (BYTE *)NULL; + void * pdu = (void *)NULL; + BYTE * buf = (BYTE *)NULL; + char * cbuf = (char *)NULL; + char * tpos = NULL; + char * qpos = NULL; + uint32_t crc32 = 0x00000000; + uint32_t magic = 0x00000000; + uint32_t device_id = 0x00000000; + uint32_t calc_crc32 = 0x00000000; + + MDBGLOG("redir","smartcard_data_in(): called"); + + if (trans == 0) { + return 0; + } + + g_memset((char *)tdata,0,sizeof(char)*MAX_STREAM); + g_memset(&ts,0,sizeof(struct stream)); + ts.data = (char *)tdata; + ts.p = ts.data; + ts.end = ts.data; + ts.size = MAX_STREAM; + r = &ts; + g_memset((char *)qdata,0,sizeof(char)*MAX_STREAM); + g_memset(&qs,0,sizeof(struct stream)); + qs.data = (char *)qdata; + qs.p = qs.data; + qs.end = qs.data; + qs.size = MAX_STREAM; + q = &qs; + g_memset((char *)odata,0,sizeof(char)*MAX_STREAM); + g_memset(&os,0,sizeof(struct stream)); + os.data = (char *)odata; + os.p = os.data; + os.end = os.data; + os.size = MAX_STREAM; + l = &os; + + s = (struct stream *)trans_get_in_s(trans); + g_memcpy(l->data,s->data,s->size); + l->size = s->size; + if ((s->p - s->data) > 0) { + l->p += (s->p - s->data); + } + if ((s->end - s->data) > 0) { + l->end = l->data + (s->end - s->data); + } + g_memcpy(q->data,s->data,s->size); + q->size = s->size; + if ((s->p - s->data) > 0) { + q->p += (s->p - s->data); + } + if ((s->end - s->data) > 0) { + q->end = q->data + (s->end - s->data); + } + // g_hexdump_file("/tmp/taskq_parent_pronto.hexdump",q->data,q->size); + in_uint32_le(q, magic); + in_uint32_le(q, rdpsc_opcode); + in_uint32_le(q, size); + in_uint32_le(q, device_id); + in_uint32_le(q, fhandle); + in_uint32_le(q, uniqid); + in_uint32_le(q, crc32); + + if (size > 0) { + int tlen = size; + trans_force_read(trans, tlen); + s->p += 28; + calc_crc32 = Crc32_ComputeBuf(0, s->p, tlen); + MDBGLOG("redir", "INFO\t[%s()]: crc32 = 0x%8.8x, calc_crc32 = 0x%8.8x", __func__, crc32, calc_crc32); + if ((rdpsc_opcode & RDPSC_READ) == RDPSC_READ) { + in_uint32_le(s, tsize); + in_uint64_le(s, toffset); + tlen -= 12; + } + else if ((rdpsc_opcode & RDPSC_WRITE) == RDPSC_WRITE) { + in_uint32_le(s, tsize); + in_uint64_le(s, toffset); + tlen -= (12 + tsize); + } + else if ((rdpsc_opcode & RDPSC_IOCTL) == RDPSC_IOCTL) { + in_uint32_le(s, tcmd); + in_uint32_le(s, tinputbufferlength); + toutputbufferlength = 4096; + if (tinputbufferlength > 0) { + tbuffer = (BYTE *)g_malloc(sizeof(BYTE) * tinputbufferlength, 1); + in_uint8a(s, tbuffer, tinputbufferlength); + } + tlen -= (8 + tinputbufferlength + tsize); + } + else if ((rdpsc_opcode & RDPSC_OPEN) == RDPSC_OPEN) { + in_uint32_le(s, tflags); + in_uint32_le(s, tshare); + in_uint32_le(s, toptions); + in_uint32_le(s, tattributes); + //tlen -= 8; + tlen -= (16 + tsize); + } + cbuf = (char *)g_malloc(sizeof(char) * tlen, 1); + buf = (BYTE *)g_malloc(sizeof(BYTE) * tlen, 1); + in_uint8a(s, (char *)cbuf, tlen); + g_memcpy((char *)buf,cbuf,tlen); + } + + MDBGLOG("redir","\n\n ** smartcard_data_in(): rdpsc_opcode = %8.8x; size = %d; uniqid = %d; fhandle = %d; buf = \"%s\"; tflags = 0x%8.8x; tsize = %d; toffset = %lu\n",rdpsc_opcode,size,uniqid,fhandle,(char *)buf,tflags,tsize,toffset); + + if (error == 0) { + int found = 0; + TC_MUTEX_LOCK(mutex_cb); + for (opid = 4; opid < MAX_PENDING; opid++) { + if (g_callbacks[opid].opid < 1) { + found = 1; + break; + } + } + if (found > 0) { + g_memset((callback *)(&(g_callbacks[opid])), 0, sizeof(callback)); + g_callbacks[opid].opid = opid; + g_callbacks[opid].type = 1; + g_callbacks[opid].smartcard = g_smartcard_arr[0]; + g_callbacks[opid].fd = g_smartcard_arr[0]->parent_sck; + g_callbacks[opid].opcode = rdpsc_opcode; + g_callbacks[opid].CompletionId = opid; + g_callbacks[opid].trans = g_smartcard_arr[0]->ccon; + g_callbacks[opid].uniqid = uniqid; + g_callbacks[opid].FileId = fhandle; + g_callbacks[opid].setData = &cb_set_data; + g_callbacks[opid].call = &cb_call; + g_callbacks[opid].callData = &cb_call_data; + g_memcpy(g_callbacks[opid].fname,buf,(size > 511)?511:size); + cb = &(g_callbacks[opid]); + } + if (found < 1) { + MDBGLOG("redir","ERROR [smartcard_data_in()]: unable to allocate callback slot (opcode = %8.8x; opid = %d)",rdpsc_opcode,opid); + error = -1; + } + else if (cb == NULL) { + MDBGLOG("redir","ERROR [smartcard_data_in()]: failed to assign callback to operation (opcode = %8.8x; opid = %d)",rdpsc_opcode,opid); + error = -1; + } + else { + switch(rdpsc_opcode) { + default: + MDBGLOG("redir","ERROR [smartcard_data_in()]: unrecognized opcode (0x%8.8x)",rdpsc_opcode); + r = trans_get_out_s(trans, MAX_STREAM); + size = 0x00000000; + crc32 = 0x00000000; + magic = RDP_PACKET_MAGIC; + out_uint32_le(r, magic); + out_uint32_le(r, RDPSC_ERROR); + out_uint32_le(r, size); + out_uint32_le(r, device_id); + out_uint32_le(r, fhandle); + out_uint32_le(r, uniqid); + out_uint32_le(r, crc32); + s_mark_end(r); + trans_force_write(trans); + r->end = r->data; + break; + } + /* send the assembled PDU to the RDP client: */ + MDBGLOG("redir","[smartcard_data_in()]: sending PDU to RDP channel..."); + s_mark_end(r); + size = r->end - r->data; + if (size > 0) { + TC_MUTEX_LOCK(mutex_out); + error = send_channel_data(g_rdpdr_chan_id, r->data, size); + TC_MUTEX_UNLOCK(mutex_out); + MDBGLOG("redir","[smartcard_data_in()]: sent. (error = %d; g_rdpdr_chan_id = %d)",error,g_rdpdr_chan_id); + // g_hexdump_file("/tmp/taskq_smartcard_pdu.hexdump", r->data, size); + if (rdpsc_opcode == RDPSC_READ) { + // g_hexdump_file("/tmp/taskq_smartcard_pdu_read.hexdump", r->data, size); + } + } + else { + MDBGLOG("redir","ERROR [smartcard_data_in()]: output PDU is empty (size == 0)"); + } + } + TC_MUTEX_UNLOCK(mutex_cb); + } + return error; +} + +/*****************************************************************************/ +static int APP_CC +filesystem_data_in(struct trans * trans) { + struct stream * s = (struct stream *)NULL; + char odata[MAX_STREAM]; + struct stream os; + char qdata[MAX_STREAM]; + struct stream qs; + char tdata[MAX_STREAM]; + struct stream ts; + struct stream * r = (struct stream *)NULL; + struct stream * q = (struct stream *)NULL; + struct stream * l = (struct stream *)NULL; + callback * cb = (callback *)NULL; + int fpath_length = 0; + int rdpfs_opcode = 0; + int size = 0; + int error = 0; + int idx = 0; + int opid = 0; + int fhandle = 0; + int uniqid = 0; + uint32_t tflags = 0x00000000; + uint32_t toptions = 0x00000000; + uint32_t tshare = 0x00000000; + uint32_t tsize = 0x00000000; + uint64_t toffset = 0x0000000000000000; + uint64_t tchangetime = 0x0000000000000000; + uint64_t tactime = 0x0000000000000000; + uint64_t tmodtime = 0x0000000000000000; + uint32_t tattributes = 0x0000000000000000; + uint32_t treserved = 0x0000000000000000; + uint32_t tinputbufferlength = 0; + uint32_t toutputbufferlength = 0; + uint32_t tcmd = 0; + BYTE * tbuffer = (BYTE *)NULL; + void * pdu = (void *)NULL; + BYTE * buf = (BYTE *)NULL; + char * cbuf = (char *)NULL; + char * tpos = NULL; + char * qpos = NULL; + uint32_t crc32 = 0x00000000; + uint32_t calc_crc32 = 0x00000000; + uint32_t magic = 0x00000000; + uint32_t device_id = 0x00000000; + + MDBGLOG("redir","INFO\t[%s()]: called (trans = %p; trans->callback_data = %p; trans->callback_data->device_id = %d) [%d, %d]",__func__,trans,trans->callback_data,((callback *)(trans->callback_data))->device_id,g_getpid(),g_gettid()); + + if (trans == 0) { + return 0; + } + + g_memset((char *)tdata,0,sizeof(char)*MAX_STREAM); + g_memset(&ts,0,sizeof(struct stream)); + ts.data = (char *)tdata; + ts.p = ts.data; + ts.end = ts.data; + ts.size = MAX_STREAM; + r = &ts; + g_memset((char *)qdata,0,sizeof(char)*MAX_STREAM); + g_memset(&qs,0,sizeof(struct stream)); + qs.data = (char *)qdata; + qs.p = qs.data; + qs.end = qs.data; + qs.size = MAX_STREAM; + q = &qs; + g_memset((char *)odata,0,sizeof(char)*MAX_STREAM); + g_memset(&os,0,sizeof(struct stream)); + os.data = (char *)odata; + os.p = os.data; + os.end = os.data; + os.size = MAX_STREAM; + l = &os; + + s = (struct stream *)trans_get_in_s(trans); + g_memcpy(l->data,s->data,s->size); + l->size = s->size; + if ((s->p - s->data) > 0) { + l->p += (s->p - s->data); + } + if ((s->end - s->data) > 0) { + l->end = l->data + (s->end - s->data); + } + g_memcpy(q->data,s->data,s->size); + q->size = s->size; + if ((s->p - s->data) > 0) { + q->p += (s->p - s->data); + } + if ((s->end - s->data) > 0) { + q->end = q->data + (s->end - s->data); + } + // g_hexdump_file("/tmp/taskq_parent_pronto.hexdump",q->data,q->size); + in_uint32_le(q, magic); + in_uint32_le(q, rdpfs_opcode); + in_uint32_le(q, size); + in_uint32_le(q, device_id); + in_uint32_le(q, fhandle); + in_uint32_le(q, uniqid); + in_uint32_le(q, crc32); + + if (size > 0) { + int tlen = size; + trans_force_read(trans, tlen); + s->p += 28; + calc_crc32 = Crc32_ComputeBuf(0, s->p, tlen); + if ((rdpfs_opcode & RDPFS_READ) == rdpfs_opcode) { + in_uint32_le(s, tsize); + in_uint64_le(s, toffset); + tlen -= 12; + } + else if ((rdpfs_opcode & RDPFS_WRITE) == rdpfs_opcode) { + in_uint32_le(s, tsize); + in_uint64_le(s, toffset); + tlen -= (12 + tsize); + } + else if ((rdpfs_opcode & RDPFS_FTRUNCATE) == rdpfs_opcode || (rdpfs_opcode & RDPFS_TRUNCATE) == rdpfs_opcode) { + in_uint64_le(s, toffset); + tlen -= 8; + } + else if ((rdpfs_opcode & RDPFS_UTIME) == rdpfs_opcode) { + in_uint64_le(s, tactime); + in_uint64_le(s, tmodtime); + tlen -= 16; + } + else if ((rdpfs_opcode & RDPFS_FSCTL) == rdpfs_opcode) { + in_uint32_le(s, tcmd); + in_uint32_le(s, tinputbufferlength); + toutputbufferlength = 4096; + if (tinputbufferlength > 0) { + tbuffer = (BYTE *)g_malloc(sizeof(BYTE) * tinputbufferlength, 1); + in_uint8a(s, tbuffer, tinputbufferlength); + } + tlen -= (8 + tinputbufferlength + tsize); + } + else if ((rdpfs_opcode & RDPFS_OPEN) == rdpfs_opcode || (rdpfs_opcode & RDPFS_CREATE) == rdpfs_opcode) { + in_uint32_le(s, tflags); + in_uint32_le(s, tshare); + in_uint32_le(s, toptions); + in_uint32_le(s, tattributes); + //tlen -= 8; + tlen -= (16 + tsize); + } + cbuf = (char *)g_malloc(sizeof(char) * tlen, 1); + buf = (BYTE *)g_malloc(sizeof(BYTE) * tlen, 1); + in_uint8a(s, (char *)cbuf, tlen); + g_memcpy((char *)buf,cbuf,tlen); + } + + MDBGLOG("redir","INFO\t[%s()]: ** rdpfs_opcode = %8.8x; size = %d; uniqid = %d; fhandle = %d; buf = \"%s\"; tflags = 0x%8.8x; tsize = %d; toffset = %lu\n",__func__,rdpfs_opcode,size,uniqid,fhandle,(char *)buf,tflags,tsize,toffset); + MDBGLOG("redir","INFO\t[%s()]: magic = 0x%8.8x, crc32 = 0x%8.8x, calc_crc32 = 0x%8.8x", __func__, magic, crc32, calc_crc32); + + if (error == 0) { + int found = 0; + TC_MUTEX_LOCK(mutex_cb); + for (opid = 4; opid < MAX_PENDING; opid++) { + if (g_callbacks[opid].opid < 1) { + found = 1; + break; + } + } + if (found > 0) { + g_memset((callback *)(&(g_callbacks[opid])), 0, sizeof(callback)); + g_callbacks[opid].opid = opid; + g_callbacks[opid].type = 1; + TC_MUTEX_LOCK(mutex_fs_arr); + g_callbacks[opid].fs = g_fs_arr[0]; + g_callbacks[opid].fd = g_fs_arr[0]->parent_sck; + g_callbacks[opid].opcode = rdpfs_opcode; + g_callbacks[opid].CompletionId = opid; + g_callbacks[opid].trans = g_fs_arr[0]->ccon; + TC_MUTEX_UNLOCK(mutex_fs_arr); + g_callbacks[opid].uniqid = uniqid; + g_callbacks[opid].FileId = fhandle; + g_callbacks[opid].setData = &cb_set_data; + g_callbacks[opid].call = &cb_call; + g_callbacks[opid].callData = &cb_call_data; + g_callbacks[opid].device_id = device_id; + g_memcpy(g_callbacks[opid].fname,buf,(size > 511)?511:size); + cb = &(g_callbacks[opid]); + } + if (found < 1) { + MDBGLOG("redir","ERROR\t[%s()]: unable to allocate callback slot (opcode = %8.8x; opid = %d)",__func__,rdpfs_opcode,opid); + error = -1; + } + else if (cb == NULL) { + MDBGLOG("redir","ERROR\t[%s()]: failed to assign callback to operation (opcode = %8.8x; opid = %d)",__func__,rdpfs_opcode,opid); + error = -1; + } + else { + if (device_id == 0 && trans->callback_data != NULL) { + device_id = ((rdpfs *)trans->callback_data)->device_id; + } + switch(rdpfs_opcode) { + case RDPFS_GETATTR: + case RDPFS_FGETATTR: + if (rdpfs_opcode == RDPFS_FGETATTR) { + MDBGLOG("redir","INFO\t[%s()]: ^^ (RDPFS_FGETATTR): device_id = %d; fhandle = %d; uniqid = %d",__func__,device_id,fhandle,uniqid); + } + else { + MDBGLOG("redir","INFO\t[%s()]: ^^ (RDPFS_GETATTR): device_id = %d; fhandle = %d; uniqid = %d",__func__,device_id,fhandle,uniqid); + } + { + DR_DRIVE_QUERY_INFORMATION_REQ ioreq; + DECLARE_GETATTR(tmp); + construct_DR_DRIVE_QUERY_INFORMATION_REQ(&ioreq); + ioreq.DeviceIoRequest.MajorFunction = IRP_MJ_QUERY_INFORMATION; + ioreq.DeviceIoRequest.DeviceId = device_id; + ioreq.DeviceIoRequest.CompletionId = opid; + ioreq.DeviceIoRequest.FileId = fhandle; + cb->FileId = fhandle; + TC_MUTEX_LOCK(&(tmp->lock)); + tmp->device_id = device_id; + tmp->fhandle = fhandle; + tmp->uniqid = uniqid; + tmp->opid = opid; + tmp->opcode = rdpfs_opcode; + TC_MUTEX_UNLOCK(&(tmp->lock)); + MDBGLOG("redir","INFO\t[%s()]: calling GETATTR_ENQ() [g_getattr_q = %p; device_id = %d, fhandle = %d, uniqid = %d, opid = %d]",__func__,g_getattr_q,device_id,fhandle,uniqid,opid); + TC_MUTEX_LOCK(mutex_getattr); + GETATTR_ENQ(tmp); + TC_MUTEX_UNLOCK(mutex_getattr); + MDBGLOG("redir","INFO\t[%s()]: GETATTR_ENQ() called. [g_getattr_q = %p]",__func__,g_getattr_q); + ioreq.FsInformationClass = FileBasicInformation; + send_DR_DRIVE_QUERY_INFORMATION_REQ(&ioreq, r); + } + break; + case RDPFS_READLINK: + MDBGLOG("redir"," ^^ (RDPFS_READLINK)"); + break; + case RDPFS_MKNOD: + MDBGLOG("redir"," ^^ (RDPFS_MKNOD)"); + break; + case RDPFS_UNLINK: + MDBGLOG("redir"," ^^ (RDPFS_UNLINK)"); + { + DR_DRIVE_SET_INFORMATION_REQ ioreq; + construct_DR_DRIVE_SET_INFORMATION_REQ(&ioreq); + ioreq.DeviceIoRequest.MajorFunction = IRP_MJ_SET_INFORMATION; + TC_MUTEX_LOCK(mutex_client_devicelist); + ioreq.DeviceIoRequest.DeviceId = device_id; + TC_MUTEX_UNLOCK(mutex_client_devicelist); + ioreq.DeviceIoRequest.CompletionId = opid; + ioreq.DeviceIoRequest.FileId = fhandle; + ioreq.FsInformationClass = FileDispositionInformation; + ioreq.Length = 0; + send_DR_DRIVE_SET_INFORMATION_REQ(&ioreq, r); + MDBGLOG("redir"," ^^ (RDPFS_UNLINK): ioreq.Length = %d; buf = \"%s\"",ioreq.Length,buf); + } + break; + case RDPFS_RMDIR: + MDBGLOG("redir"," ^^ (RDPFS_RMDIR)"); + { + DR_DRIVE_SET_INFORMATION_REQ ioreq; + construct_DR_DRIVE_SET_INFORMATION_REQ(&ioreq); + ioreq.DeviceIoRequest.MajorFunction = IRP_MJ_SET_INFORMATION; + ioreq.DeviceIoRequest.DeviceId = device_id; + ioreq.DeviceIoRequest.CompletionId = opid; + ioreq.DeviceIoRequest.FileId = fhandle; + ioreq.FsInformationClass = FileDispositionInformation; + ioreq.Length = 0; + send_DR_DRIVE_SET_INFORMATION_REQ(&ioreq, r); + MDBGLOG("redir"," ^^ (RDPFS_RMDIR): ioreq.Length = %d; buf = \"%s\"",ioreq.Length,buf); + } + break; + case RDPFS_SYMLINK: + MDBGLOG("redir"," ^^ (RDPFS_SYMLINK)"); + break; + case RDPFS_RENAME: + MDBGLOG("redir"," ^^ (RDPFS_RENAME)"); + { + DR_DRIVE_SET_INFORMATION_REQ ioreq; + char fpath[512]; + BYTE wpath[1024]; + int cnt = 0; + char * iptr = NULL; + char * optr = NULL; + int inum = 0; + int onum = 0; + size_t tflen = 0; + g_memset(&ioreq,0,sizeof(DR_CREATE_REQ)); + g_memset((char *)fpath,0,sizeof(char)*512); + g_memset((BYTE *)wpath,0,sizeof(BYTE)*1024); + char * tpos = (char *)NULL; + char * tend = (char *)NULL; + int diff = 0; + fpath_length = g_strlen(buf) + 1; + iptr = buf; + optr = wpath; + inum = fpath_length; + onum = 1024; + g_outstr(&optr,&onum,&iptr,&inum); + cnt = fpath_length * 2; + for (idx = 0; idx < cnt; idx++) { + if (wpath[idx] == '/') { + wpath[idx] = '\\'; + } + } + construct_DR_DRIVE_SET_INFORMATION_REQ(&ioreq); + ioreq.DeviceIoRequest.MajorFunction = IRP_MJ_SET_INFORMATION; + ioreq.DeviceIoRequest.DeviceId = device_id; + ioreq.DeviceIoRequest.CompletionId = opid; + ioreq.DeviceIoRequest.FileId = fhandle; + ioreq.DeviceIoRequest.MajorFunction = IRP_MJ_SET_INFORMATION; + ioreq.DeviceIoRequest.MinorFunction = 0x00000000; + ioreq.FsInformationClass = FileRenameInformation; + ioreq.SetBuffer.RenameInformation.ReplaceIfExists = 0x01; + ioreq.SetBuffer.RenameInformation.RootDirectory = 0x00; + ioreq.SetBuffer.RenameInformation.FileNameLength = fpath_length * 2; + if (ioreq.SetBuffer.RenameInformation.FileNameLength > 0) { + tflen = ioreq.SetBuffer.RenameInformation.FileNameLength; + ioreq.SetBuffer.RenameInformation.FileName = (BYTE *)g_malloc(sizeof(BYTE) * (ioreq.SetBuffer.RenameInformation.FileNameLength + 2), 1); + g_memcpy(ioreq.SetBuffer.RenameInformation.FileName,wpath,tflen); + } + ioreq.Length = 6 + ioreq.SetBuffer.RenameInformation.FileNameLength; + tpos = r->p; + send_DR_DRIVE_SET_INFORMATION_REQ_rename(&ioreq, r); + tend = r->p; + { + int fdx = 0; + char tout[1024]; + g_memset(tout,0,sizeof(char)*1024); + for (fdx=0;fdxFileId = fhandle; + cb->userdata = (BYTE *)NULL; + cb->actime = tactime; + cb->modtime = tmodtime; + TC_MUTEX_LOCK(&(tmp->lock)); + tmp->device_id = device_id; + tmp->fhandle = fhandle; + tmp->uniqid = uniqid; + tmp->opcode = rdpfs_opcode; + TC_MUTEX_UNLOCK(&(tmp->lock)); + TC_MUTEX_LOCK(mutex_getattr); + GETATTR_ENQ(tmp); + TC_MUTEX_UNLOCK(mutex_getattr); + ioreq.FsInformationClass = FileBasicInformation; + ioreq.Length = sizeof(FILE_BASIC_INFORMATION); + send_DR_DRIVE_QUERY_INFORMATION_REQ(&ioreq, r); + } + break; + case RDPFS_OPEN: + MDBGLOG("redir"," ^^ (RDPFS_OPEN): tflags = 0x%8.8x",tflags); + { + DR_CREATE_REQ ioreq; + char fpath[512]; + BYTE wpath[1024]; + int cnt = 0; + char * iptr = NULL; + char * optr = NULL; + int inum = 0; + int onum = 0; + g_memset(&ioreq,0,sizeof(DR_CREATE_REQ)); + g_memset((char *)fpath,0,sizeof(char)*512); + g_memset((BYTE *)wpath,0,sizeof(BYTE)*1024); + fpath_length = g_strlen(buf) + 1; + iptr = buf; + optr = wpath; + inum = fpath_length; + onum = 1024; + g_outstr(&optr,&onum,&iptr,&inum); + cnt = fpath_length * 2; + for (idx = 0; idx < cnt; idx++) { + if (wpath[idx] == '/') { + wpath[idx] = '\\'; + } + } + pdu = (void *)(&ioreq); + construct_DR_CREATE_REQ(&ioreq); + ioreq.DeviceIoRequest.DeviceId = device_id; + ioreq.DeviceIoRequest.CompletionId = opid; + ioreq.DeviceIoRequest.MajorFunction = IRP_MJ_CREATE; + ioreq.DeviceIoRequest.MinorFunction = 0x00000000; + ioreq.CreateDisposition = FILE_OPEN; + ioreq.CreateOptions = toptions; + ioreq.DesiredAccess = tflags; + ioreq.SharedAccess = tshare; + ioreq.FileAttributes = tattributes; + ioreq.PathLength = cnt; + if (ioreq.PathLength > 2) { + g_memcpy((BYTE *)(ioreq.Path),wpath,cnt); + } + send_DR_CREATE_REQ(&ioreq, r); + { + int fdx = 0; + char tout[1024]; + g_memset(tout,0,sizeof(char)*1024); + for (fdx=0;fdxopid = opid; + cb->FileId = fhandle; + ioreq.Length = tsize; + ioreq.Offset = toffset; + send_DR_READ_REQ(&ioreq, r); + MDBGLOG("redir"," ^^ (RDPFS_READ): ioreq.Length = %d; ioreq.Offset = %llu; tsize = %d; toffset = %llu; buf = \"%s\"; ioreq.DeviceIoRequest.DeviceId = %d; ioreq.DeviceIoRequest.FileId = %d; ioreq.DeviceIoRequest.MajorFunction = 0x%8.8x",ioreq.Length,ioreq.Offset,tsize,toffset,buf,ioreq.DeviceIoRequest.DeviceId,ioreq.DeviceIoRequest.FileId,ioreq.DeviceIoRequest.MajorFunction); + } + break; + case RDPFS_WRITE: + MDBGLOG("redir"," ^^ (RDPFS_WRITE)"); + { + DR_WRITE_REQ ioreq; + construct_DR_WRITE_REQ(&ioreq); + ioreq.DeviceIoRequest.MajorFunction = IRP_MJ_WRITE; + ioreq.DeviceIoRequest.DeviceId = device_id; + ioreq.DeviceIoRequest.CompletionId = opid; + ioreq.DeviceIoRequest.FileId = fhandle; + ioreq.Length = tsize; + ioreq.Offset = toffset; + if (ioreq.Length < MAX_STREAM) { + if (ioreq.Length > 0) { + ioreq.WriteData = (BYTE *)g_malloc(sizeof(BYTE) * ioreq.Length, 1); + in_uint8a(s, ioreq.WriteData, ioreq.Length); + } + } + //MDBGLOG("redir"," ^^ (RDPFS_WRITE): ioreq.WriteData = \"%s\"; ioreq.Length = %d; ioreq.Offset = %d",ioreq.WriteData,ioreq.Length,ioreq.Offset); + send_DR_WRITE_REQ(&ioreq, r); + } + break; + case RDPFS_STATFS: + MDBGLOG("redir"," ^^ (RDPFS_STATFS)"); + { + DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ ioreq; + construct_DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ(&ioreq); + ioreq.DeviceIoRequest.MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION; + ioreq.DeviceIoRequest.DeviceId = device_id; + ioreq.DeviceIoRequest.CompletionId = opid; + ioreq.DeviceIoRequest.FileId = fhandle; + ioreq.FsInformationClass = FileFsFullSizeInformation; + cb->FileId = fhandle; + send_DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ(&ioreq, r); + } + break; + case RDPFS_FLUSH: + MDBGLOG("redir"," ^^ (RDPFS_FLUSH)"); + { + DR_DRIVE_CONTROL_REQ ioreq; + construct_DR_DRIVE_CONTROL_REQ(&ioreq); + ioreq.Header.DeviceIoRequest.MajorFunction = IRP_MJ_FLUSH_BUFFERS; + ioreq.Header.DeviceIoRequest.DeviceId = device_id; + ioreq.Header.DeviceIoRequest.CompletionId = opid; + ioreq.Header.DeviceIoRequest.FileId = fhandle; + cb->FileId = fhandle; + send_DR_DRIVE_CONTROL_REQ(&ioreq, r); + } + break; + case RDPFS_RELEASE: + MDBGLOG("redir"," ^^ (RDPFS_RELEASE)"); + { + DR_DRIVE_CLOSE_REQ ioreq; + g_memset(&ioreq,0,sizeof(DR_DRIVE_CLOSE_REQ)); + construct_DR_DRIVE_CLOSE_REQ(&ioreq); + ioreq.DeviceCloseRequest.DeviceIoRequest.MajorFunction = IRP_MJ_CLOSE; + MDBGLOG("redir","INFO\t[%s()]: about to lock ... [%d, %d]",__func__,g_getpid(),g_gettid()); + TC_MUTEX_LOCK(mutex_client_devicelist); + MDBGLOG("redir","INFO\t[%s()]: locked . [%d, %d]",__func__,g_getpid(),g_gettid()); + MDBGLOG("redir","INFO\t[%s()]: about to lock ... [%d, %d]",__func__,g_getpid(),g_gettid()); + TC_MUTEX_LOCK(mutex_fs_arr); + MDBGLOG("redir","INFO\t[%s()]: locked . [%d, %d]",__func__,g_getpid(),g_gettid()); + ioreq.DeviceCloseRequest.DeviceIoRequest.DeviceId = device_id; + TC_MUTEX_UNLOCK(mutex_fs_arr); + MDBGLOG("redir","INFO\t[%s()]: unlocked . [%d, %d]",__func__,g_getpid(),g_gettid()); + TC_MUTEX_UNLOCK(mutex_client_devicelist); + MDBGLOG("redir","INFO\t[%s()]: unlocked . [%d, %d]",__func__,g_getpid(),g_gettid()); + ioreq.DeviceCloseRequest.DeviceIoRequest.FileId = fhandle; + ioreq.DeviceCloseRequest.DeviceIoRequest.CompletionId = opid; + cb->FileId = fhandle; + send_DR_DRIVE_CLOSE_REQ(&ioreq, r); + MDBGLOG("redir","filesystem_data_in(): [RDPFS_RELEASE] request sent (FileId = %d)",ioreq.DeviceCloseRequest.DeviceIoRequest.FileId); + } + break; + case RDPFS_FSYNC: + MDBGLOG("redir"," ^^ (RDPFS_FSYNC)"); + break; + case RDPFS_OPENDIR: + MDBGLOG("redir"," ^^ (RDPFS_OPENDIR)"); + { + DR_CREATE_REQ ioreq; + char fpath[512]; + BYTE wpath[1024]; + int cnt = 0; + char * iptr = NULL; + char * optr = NULL; + int inum = 0; + int onum = 0; + g_memset(&ioreq,0,sizeof(DR_CREATE_REQ)); + g_memset((char *)fpath,0,sizeof(char)*512); + g_memset((BYTE *)wpath,0,sizeof(BYTE)*1024); + MDBGLOG("redir"," ^^ (RDPFS_OPENDIR) here 1"); + fpath_length = g_strlen(buf) + 1; + iptr = buf; + optr = wpath; + inum = fpath_length; + onum = 1024; + g_outstr(&optr,&onum,&iptr,&inum); + cnt = fpath_length * 2; + for (idx = 0; idx < cnt; idx++) { + if (wpath[idx] == '/') { + wpath[idx] = '\\'; + } + } + pdu = (void *)(&ioreq); + construct_DR_CREATE_REQ(&ioreq); + MDBGLOG("redir"," ^^ (RDPFS_OPENDIR) here 5"); + ioreq.DeviceIoRequest.DeviceId = device_id; + ioreq.DeviceIoRequest.CompletionId = opid; + ioreq.DeviceIoRequest.MajorFunction = IRP_MJ_CREATE; + ioreq.DeviceIoRequest.MinorFunction = 0x00000000; + ioreq.CreateDisposition = FILE_OPEN; +// ioreq.DesiredAccess = FILE_LIST_DIRECTORY | FILE_TRAVERSE | FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE | FILE_DELETE_CHILD; +// ioreq.SharedAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; +// ioreq.DesiredAccess = FILE_LIST_DIRECTORY | FILE_TRAVERSE; + ioreq.DesiredAccess = MAXIMUM_ALLOWED; + ioreq.SharedAccess = FILE_SHARE_READ; + ioreq.PathLength = cnt; + if (ioreq.PathLength > 2) { + g_memcpy((BYTE *)(ioreq.Path),wpath,cnt); + } + send_DR_CREATE_REQ(&ioreq, r); + { + int fdx = 0; + char tout[1024]; + g_memset(tout,0,sizeof(char)*1024); + for (fdx=0;fdx 2) { + for (idx = 0; idx < fpath_length; idx++) { + wpath[cnt] = (buf[idx] == '/') ? '\\' : buf[idx]; + cnt += 2; + } + if (wpath[(cnt - 4)] != '\\' || wpath[(cnt - 2)] == '*') { + wpath[cnt] = '\\'; + cnt += 2; + wpath[cnt] = '*'; + cnt += 2; + } + cnt += 2; /* corresponds to the final '\0' string terminator */ + } + construct_DR_DRIVE_QUERY_DIRECTORY_REQ(&ioreq); + ioreq.DeviceIoRequest.MajorFunction = IRP_MJ_DIRECTORY_CONTROL; + ioreq.DeviceIoRequest.MinorFunction = IRP_MN_QUERY_DIRECTORY; + ioreq.DeviceIoRequest.DeviceId = device_id; + ioreq.DeviceIoRequest.FileId = fhandle; + cb->FileId = fhandle; + ioreq.DeviceIoRequest.CompletionId = opid; + ioreq.FsInformationClass = FileBothDirectoryInformation; + ioreq.InitialQuery = 0x01; + ioreq.PathLength = cnt; + g_memcpy((BYTE *)(ioreq.Path),wpath,ioreq.PathLength); + { + int fdx = 0; + char tout[1024]; + g_memset(tout,0,sizeof(char)*1024); + for (fdx=0;fdxFileId = fhandle; + send_DR_DRIVE_CLOSE_REQ(&ioreq, r); + } + break; + case RDPFS_FSYNCDIR: + MDBGLOG("redir"," ^^ (RDPFS_FSYNCDIR)"); + break; + case RDPFS_INIT: + MDBGLOG("redir"," ^^ (RDPFS_INIT)"); + { + struct stream * t = (struct stream *)NULL; + DR_CREATE_REQ tmp; + DR_CREATE_REQ * ioreq = (DR_CREATE_REQ *)NULL; + ioreq = &tmp; + g_memset(ioreq,0,sizeof(DR_CREATE_REQ)); + construct_DR_CREATE_REQ(ioreq); + ioreq->DeviceIoRequest.DeviceId = device_id; + ioreq->DeviceIoRequest.CompletionId = opid; + ioreq->PathLength = 2; +// ioreq->DesiredAccess = FILE_LIST_DIRECTORY | FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | FILE_TRAVERSE | FILE_DELETE_CHILD; +// ioreq->DesiredAccess = FILE_LIST_DIRECTORY | FILE_TRAVERSE; + ioreq->DesiredAccess = MAXIMUM_ALLOWED; + ioreq->CreateDisposition = FILE_OPEN; + ioreq->CreateOptions = FILE_DIRECTORY_FILE; +// ioreq->SharedAccess = FILE_SHARE_READ | FILE_SHARE_WRITE; + ioreq->SharedAccess = FILE_SHARE_READ; + ioreq->FileAttributes = FILE_ATTRIBUTE_DIRECTORY; + send_DR_CREATE_REQ(ioreq, r); + // g_hexdump_file("/tmp/taskq_parent_init.hexdump", r->data, (int)(r->p - r->data)); + cb->CompletionId = opid; + } + break; + case RDPFS_DESTROY: + MDBGLOG("redir"," ^^ (RDPFS_DESTROY)"); + { + DR_CLOSE_REQ ioreq; + construct_DR_CLOSE_REQ(&ioreq); + ioreq.DeviceIoRequest.DeviceId = device_id; + ioreq.DeviceIoRequest.MajorFunction = IRP_MJ_CLOSE; + send_DR_CLOSE_REQ(&ioreq, r); + } + break; + case RDPFS_ACCESS: + MDBGLOG("redir"," ^^ (RDPFS_ACCESS)"); + break; + case RDPFS_CREATE: + MDBGLOG("redir"," ^^ (RDPFS_CREATE)"); + { + DR_CREATE_REQ ioreq; + char fpath[512]; + BYTE wpath[1024]; + int cnt = 0; + char * iptr = NULL; + char * optr = NULL; + int inum = 0; + int onum = 0; + g_memset(&ioreq,0,sizeof(DR_CREATE_REQ)); + g_memset((char *)fpath,0,sizeof(char)*512); + g_memset((BYTE *)wpath,0,sizeof(BYTE)*1024); + fpath_length = g_strlen(buf) + 1; + iptr = buf; + optr = wpath; + inum = fpath_length; + onum = 1024; + g_outstr(&optr,&onum,&iptr,&inum); + cnt = fpath_length * 2; + for (idx = 0; idx < cnt; idx++) { + if (wpath[idx] == '/') { + wpath[idx] = '\\'; + } + } + pdu = (void *)(&ioreq); + construct_DR_CREATE_REQ(&ioreq); + ioreq.DeviceIoRequest.DeviceId = device_id; + ioreq.DeviceIoRequest.CompletionId = opid; + ioreq.DeviceIoRequest.MajorFunction = IRP_MJ_CREATE; + ioreq.DeviceIoRequest.MinorFunction = 0x00000000; + ioreq.CreateDisposition = FILE_CREATE; + ioreq.CreateOptions = FILE_NON_DIRECTORY_FILE | toptions; + ioreq.DesiredAccess = tflags; + ioreq.SharedAccess = tshare; + ioreq.FileAttributes = tattributes; + ioreq.PathLength = cnt; + if (ioreq.PathLength > 2) { + g_memcpy((BYTE *)(ioreq.Path),wpath,cnt); + } + send_DR_CREATE_REQ(&ioreq, r); + { + int fdx = 0; + char tout[1024]; + g_memset(tout,0,sizeof(char)*1024); + for (fdx=0;fdx 2) { + g_memcpy((BYTE *)(ioreq.Path),wpath,cnt); + } + send_DR_CREATE_REQ(&ioreq, r); + { + int fdx = 0; + char tout[1024]; + g_memset(tout,0,sizeof(char)*1024); + for (fdx=0;fdxend = r->data; + break; + } + /* send the assembled PDU to the RDP client: */ + MDBGLOG("redir","[filesystem_data_in()]: sending PDU to RDP channel..."); + s_mark_end(r); + size = r->end - r->data; + if (size > 0) { + TC_MUTEX_LOCK(mutex_out); + error = send_channel_data(g_rdpdr_chan_id, r->data, size); + TC_MUTEX_UNLOCK(mutex_out); + MDBGLOG("redir","INFO\t[%s()]: sent. (error = %d; g_rdpdr_chan_id = %d)",__func__,error,g_rdpdr_chan_id); + } + else { + MDBGLOG("redir","ERROR\t[%s()]: output PDU is empty (size == 0)",__func__); + } + } + TC_MUTEX_UNLOCK(mutex_cb); + } + return error; +} + + +/*****************************************************************************/ +/****** Operation IDs ******/ +/*****************************************************************************/ + +/*****************************************************************************/ +static int APP_CC get_opid(void * idev) { + int rv = 0; + rdpfs * fs = (rdpfs *)idev; + if (fs == NULL) { + rv = -1; + } + else { + if (fs->top_opid == 0) { + fs->top_opid++; + } + rv = fs->top_opid++; + register_opid(fs, rv); + } + return rv; +} + +/*****************************************************************************/ +static int APP_CC register_opid(void * idev, int opid) { + int rv = -1; + int idx = 0; + int tmp = -1; + rdpfs * dev = (rdpfs *)idev; + if (dev == NULL) { + rv = -1; + } + else { + for (idx = 0; idx < MAX_PENDING; idx++) { + if ((tmp < 0) && (dev->pending_opids[idx] == 0)) { + tmp = idx; + rv = idx; + dev->pending_opids[idx] = opid; + } + else if (dev->pending_opids[idx] == opid) { + /* ERROR: the opid is already registered */ + rv = -1; + if (tmp > -1) { + dev->pending_opids[tmp] = 0; + } + MDBGLOG("redir","ERROR\t[%s()]: \"%d\" is already registered at position %d",__func__,opid,idx); + break; + } + } + } + if (rv > -1) { + if (dev->callbacks != NULL) { + dev->callbacks[rv].opid = opid; + dev->callbacks[rv].type = 0; + dev->callbacks[rv].fs = dev; + dev->callbacks[rv].fd = dev->parent_sck; + dev->callbacks[rv].trans = dev->ccon; + } + rv = 0; + } + return rv; +} + +/*****************************************************************************/ +static int APP_CC strike_opid(void * idev, int opid) { + int rv = 0; + rdpfs * fs = (rdpfs *)idev; + rv = opid_is_registered(fs, opid); + if (rv > 0) { + fs->pending_opids[rv] = 0; + if (fs->callbacks != NULL) { + if (fs->callbacks[rv].userdata != NULL && fs->callbacks[rv].length > 0) { + g_memset(fs->callbacks[rv].userdata,0,fs->callbacks[rv].length); + //g_free(fs->callbacks[rv].userdata); + fs->callbacks[rv].userdata = (BYTE *)NULL; + } + g_memset(&(fs->callbacks[rv]),0,sizeof(callback)); + //g_free(fs->callbacks[rv]); + //fs->callbacks[rv] = (callback *)NULL; + } + } + return rv; +} + +/*****************************************************************************/ +static int APP_CC opid_is_registered(void * idev, int opid) { + int rv = 0; + int idx = 0; + rdpfs * fs = (rdpfs *)idev; + if (fs == NULL) { + rv = -1; + } + else { + for (idx = 0; idx < MAX_PENDING; idx++) { + if (fs->pending_opids[idx] == opid) { + rv = idx; + break; + } + } + } + return rv; +} + +/*****************************************************************************/ +static int APP_CC +cb_set_data(struct _callback * self, int length, const BYTE * data) { + int rv = 0; + return rv; +} + +static int APP_CC +cb_set_func(struct _callback * self, void (*func)(struct _rdpfs *, int, tbus, struct trans *, DWORD, DWORD, int, BYTE *)) { + int rv = 0; + return rv; +} + +static void * APP_CC +cb_call(void * inarg) { + struct _callback * self = (struct _callback *)inarg; + if ((self != NULL) && (self->func != NULL)) { + self->func( + self->fs, + self->type, + self->fd, + self->trans, + self->CompletionId, + self->opcode, + self->length, + self->userdata); + } + else { + MDBGLOG("redir","ERROR\t[%s()]: self->func is NULL",__func__); + } +} + +static int APP_CC +cb_call_data(struct _callback * self, int length, const BYTE * data) { + int rv = 0; + rv = self->setData(self, length, data); + if (!rv) { + self->call(self); + } + return rv; +} + +static int APP_CC +get_opcode_from_opid(int opid) { + int rv = -1; + int i = 0; + int tmp = 0; + TC_MUTEX_LOCK(mutex_fs_arr); + if ((opid > -1) && (g_fs_arr != NULL) && (g_fs_count > 0)) { + for (i = 0; i < g_fs_count; i++) { + if (g_fs_arr[i] != NULL) { + tmp = opid_is_registered(g_fs_arr[i], opid); + if (tmp > 0) { + rv = g_fs_arr[i]->callbacks[tmp].opcode; + if (rv > -1) { + break; + } + } + } + } + } + TC_MUTEX_UNLOCK(mutex_fs_arr); + return rv; +} + +static callback * APP_CC +get_callback_from_opid(int opid) { + callback * rv = (callback *)NULL; + int i = 0; + int tmp = 0; + TC_MUTEX_LOCK(mutex_fs_arr); + if ((opid > -1) && (g_fs_arr != NULL) && (g_fs_count > 0)) { + for (i = 0; i < g_fs_count; i++) { + if (g_fs_arr[i] != NULL) { + tmp = opid_is_registered(g_fs_arr[i], opid); + if (tmp > 0) { + rv = &(g_fs_arr[i]->callbacks[tmp]); + if (rv != NULL) { + break; + } + } + } + } + } + TC_MUTEX_UNLOCK(mutex_fs_arr); + return rv; +} + +static void APP_CC cb_send_buf(struct _rdpfs * fs, int type, tbus fd, struct trans * trans, DWORD CompletionId, DWORD opcode, int length, BYTE * data) { + int res = 0; + int fhandle = 0; + int uniqid = 0; + uint32_t crc32 = 0x00000000; + const uint32_t magic = RDP_PACKET_MAGIC; + uint32_t device_id = 0x00000000; + struct stream * s = (struct stream *)NULL; + MDBGLOG("redir","cb_send_buf(): type = %d; fd = %d; CompletionId = %8.8x, opcode = %8.8x, length = %d",type,fd,CompletionId,opcode,length); + opcode = opcode | RDPFS_REPLY; + if (type == 1) { + if (trans == NULL) { + MDBGLOG("redir","ERROR\t[%s()]: \"trans\" is not a valid transmission channel",__func__); + } + else { + if (length > 0 && data != NULL) { + crc32 = Crc32_ComputeBuf(0, data, length); + } + s = trans_get_out_s(trans, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, opcode); + out_uint32_le(s, length); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + if ((length > 0) && (data != NULL)) { + out_uint8a(s, data, length); + } + s_mark_end(s); + MDBGLOG("redir","INFO\t[%s()]: sending %d bytes to child filesystem handler (\"trans\" mode)",__func__,(int)(s->end - s->data)); + res = trans_force_write(trans); + } + } + else { + if (length > 0 && data != NULL) { + crc32 = Crc32_ComputeBuf(0, data, length); + } + make_stream(s); + init_stream(s, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, opcode); + out_uint32_le(s, length); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + if ((length > 0) && (data != NULL)) { + out_uint8a(s, data, length); + } + s_mark_end(s); + if (fd > 0) { + MDBGLOG("redir","INFO\t[%s()]: sending %d bytes to child filesystem handler (\"non-trans\" mode)",__func__,(int)(s->end - s->data)); + res = g_tcp_send(fd, s->data, (int)(s->end - s->data), 0); + } + else { + MDBGLOG("redir","ERROR\t[%s()]: fd is not a valid file descriptor (fd = %d)",__func__,fd); + } + } + //free_stream(s); +} + +static void APP_CC cb_send_bare(struct _rdpfs * fs, int type, tbus fd, struct trans * trans, DWORD CompletionId, DWORD opcode, int length, BYTE * data) { + int res = 0; + int fhandle = 0; + int uniqid = 0; + uint32_t crc32 = 0x00000000; + const uint32_t magic = RDP_PACKET_MAGIC; + uint32_t device_id = 0x00000000; + struct stream * s = (struct stream *)NULL; + MDBGLOG("redir","cb_send_bare(): type = %d; fd = %d; CompletionId = %8.8x, opcode = %8.8x, length = %d",type,fd,CompletionId,opcode,length); + opcode = RDPFS_REPLY; + if (type == 1) { + if (trans == NULL) { + MDBGLOG("redir","ERROR [cb_send_buf()]: \"trans\" is not a valid transmission channel"); + } + else { + if (length > 0 && data != NULL) { + crc32 = Crc32_ComputeBuf(0, data, length); + } + s = trans_get_out_s(trans, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, opcode); + out_uint32_le(s, length); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + if ((length > 0) && (data != NULL)) { + out_uint8a(s, data, length); + } + s_mark_end(s); + MDBGLOG("redir","cb_send_buf(): sending %d bytes to child filesystem handler (\"trans\" mode)",(int)(s->end - s->data)); + res = trans_force_write(trans); + } + } + else { + if (length > 0 && data != NULL) { + crc32 = Crc32_ComputeBuf(0, data, length); + } + make_stream(s); + init_stream(s, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, opcode); + out_uint32_le(s, length); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + if ((length > 0) && (data != NULL)) { + out_uint8a(s, data, length); + } + s_mark_end(s); + if (fd > 0) { + MDBGLOG("redir","cb_send_buf(): sending %d bytes to child filesystem handler (\"non-trans\" mode)",(int)(s->end - s->data)); + res = g_tcp_send(fd, s->data, (int)(s->end - s->data), 0); + } + else { + MDBGLOG("redir","ERROR [cb_send_buf()]: fd is not a valid file descriptor (fd = %d)",fd); + } + } + //free_stream(s); +} + +/***/ +char * APP_CC ntstatus_string(uint32_t ival) { + char * rv = (char *)NULL; + int idx = 0; + int lmt = 0; + + lmt = sizeof(NT_errors) / sizeof(value_string); + for (idx = 0; idx < lmt; idx++) { + if (NT_errors[idx].value == ival) { + rv = (char *)NT_errors[idx].strptr; + break; + } + } + + return rv; +} + +void test_serial_port(int device_id) { + int lfd = 0; + lfd = open("/tmp/testfifo", O_WRONLY); + if (lfd > 0) { + char lbuf[6] = {'a','b','c','d','e',0}; + g_fifo_write(lfd,lbuf,5); + close(lfd); + } + else { + MDBGLOG("redir","no good :("); + } +} + +void test_serial_port_old(int device_id) { + char rdata[MAX_STREAM]; + DR_PORT_CREATE_REQ lreq; + DR_PORT_CREATE_REQ * req = &lreq; + struct stream rs; + struct stream * r = &rs; + size_t size = 0; + + g_memset(rdata,0,sizeof(char)*MAX_STREAM); + r->data = rdata; + r->p = r->data; + r->end = r->data; + r->size = MAX_STREAM; + + construct_DR_CREATE_REQ(req); + req->DeviceIoRequest.DeviceId = device_id; + req->DeviceIoRequest.MajorFunction = IRP_MJ_CREATE; + req->DeviceIoRequest.CompletionId = 7; + req->DesiredAccess = 0x00100080; + req->SharedAccess = 0x00000007; + req->CreateDisposition = 0x00000001; + req->CreateOptions = 0x00000060; + + send_DR_CREATE_REQ(req, r); + + s_mark_end(r); + size = r->end - r->data; + + if (size > 0) { + TC_MUTEX_LOCK(mutex_out); + send_channel_data(g_rdpdr_chan_id, r->data, size); + TC_MUTEX_UNLOCK(mutex_out); + } +} + +static inline int APP_CC is_filesystem(int device_idx) { + if (TC_MUTEX_TRYLOCK(mutex_client_devicelist) == 0) { + if (device_idx < 0 || g_client_devicelist == NULL || device_idx > g_client_devicelist->DeviceCount || g_client_devicelist->DeviceList[device_idx] == NULL) { + TC_MUTEX_UNLOCK(mutex_client_devicelist); + return 0; + } + else if (g_client_devicelist->DeviceList[device_idx]->DeviceType == RDPDR_DTYP_FILESYSTEM) { + TC_MUTEX_UNLOCK(mutex_client_devicelist); + return 1; + } + else { + TC_MUTEX_UNLOCK(mutex_client_devicelist); + return 0; + } + } + else { + if (device_idx < 0 || g_client_devicelist == NULL || device_idx > g_client_devicelist->DeviceCount || g_client_devicelist->DeviceList[device_idx] == NULL) { + return 0; + } + else if (g_client_devicelist->DeviceList[device_idx]->DeviceType == RDPDR_DTYP_FILESYSTEM) { + return 1; + } + else { + return 0; + } + } +} + +static inline int APP_CC is_port(int device_idx) { + if (TC_MUTEX_TRYLOCK(mutex_client_devicelist) == 0) { + if (device_idx < 0 || g_client_devicelist == NULL || device_idx > g_client_devicelist->DeviceCount || g_client_devicelist->DeviceList[device_idx] == NULL) { + TC_MUTEX_UNLOCK(mutex_client_devicelist); + return 0; + } + else if (g_client_devicelist->DeviceList[device_idx]->DeviceType == RDPDR_DTYP_SERIAL || g_client_devicelist->DeviceList[device_idx]->DeviceType == RDPDR_DTYP_PARALLEL) { + TC_MUTEX_UNLOCK(mutex_client_devicelist); + return 1; + } + else { + TC_MUTEX_UNLOCK(mutex_client_devicelist); + return 0; + } + } + else { + if (device_idx < 0 || g_client_devicelist == NULL || device_idx > g_client_devicelist->DeviceCount || g_client_devicelist->DeviceList[device_idx] == NULL) { + return 0; + } + else if (g_client_devicelist->DeviceList[device_idx]->DeviceType == RDPDR_DTYP_SERIAL || g_client_devicelist->DeviceList[device_idx]->DeviceType == RDPDR_DTYP_PARALLEL) { + return 1; + } + else { + return 0; + } + } +} + +static inline int APP_CC is_serial(int device_idx) { + if (device_idx < 0 || g_client_devicelist == NULL || device_idx > g_client_devicelist->DeviceCount || g_client_devicelist->DeviceList[device_idx] == NULL) { + return 0; + } + else if (g_client_devicelist->DeviceList[device_idx]->DeviceType == RDPDR_DTYP_SERIAL) { + return 1; + } + else { + return 0; + } +} + +static inline int APP_CC is_parallel(int device_idx) { + if (device_idx < 0 || g_client_devicelist == NULL || device_idx > g_client_devicelist->DeviceCount || g_client_devicelist->DeviceList[device_idx] == NULL) { + return 0; + } + else if (g_client_devicelist->DeviceList[device_idx]->DeviceType == RDPDR_DTYP_PARALLEL) { + return 1; + } + else { + return 0; + } +} + +static inline int APP_CC is_printer(int device_idx) { + if (TC_MUTEX_TRYLOCK(mutex_client_devicelist) == 0) { + if (device_idx < 0 || g_client_devicelist == NULL || device_idx > g_client_devicelist->DeviceCount || g_client_devicelist->DeviceList[device_idx] == NULL) { + TC_MUTEX_UNLOCK(mutex_client_devicelist); + return 0; + } + else if (g_client_devicelist->DeviceList[device_idx]->DeviceType == RDPDR_DTYP_PRINT) { + TC_MUTEX_UNLOCK(mutex_client_devicelist); + return 1; + } + else { + TC_MUTEX_UNLOCK(mutex_client_devicelist); + return 0; + } + } + else { + if (device_idx < 0 || g_client_devicelist == NULL || device_idx > g_client_devicelist->DeviceCount || g_client_devicelist->DeviceList[device_idx] == NULL) { + return 0; + } + else if (g_client_devicelist->DeviceList[device_idx]->DeviceType == RDPDR_DTYP_PRINT) { + return 1; + } + else { + return 0; + } + } +} + +static inline int APP_CC is_smartcard(int device_idx) { + if (TC_MUTEX_TRYLOCK(mutex_client_devicelist) == 0) { + if (device_idx < 0 || g_client_devicelist == NULL || device_idx > g_client_devicelist->DeviceCount || g_client_devicelist->DeviceList[device_idx] == NULL) { + TC_MUTEX_UNLOCK(mutex_client_devicelist); + return 0; + } + else if (g_client_devicelist->DeviceList[device_idx]->DeviceType == RDPDR_DTYP_SMARTCARD) { + TC_MUTEX_UNLOCK(mutex_client_devicelist); + return 1; + } + else { + TC_MUTEX_UNLOCK(mutex_client_devicelist); + return 0; + } + } + else { + if (device_idx < 0 || g_client_devicelist == NULL || device_idx > g_client_devicelist->DeviceCount || g_client_devicelist->DeviceList[device_idx] == NULL) { + return 0; + } + else if (g_client_devicelist->DeviceList[device_idx]->DeviceType == RDPDR_DTYP_SMARTCARD) { + return 1; + } + else { + return 0; + } + } +} + +static APP_CC int get_device_index(int DeviceId) { + int rv = -1; + int idx = 0; + + if (TC_MUTEX_TRYLOCK(mutex_client_devicelist) == 0) { + if (DeviceId < 0 || g_client_devicelist == NULL || g_client_devicelist->DeviceList == NULL || g_client_devicelist->DeviceCount < 1) { + rv = -1; + } + else for (idx = 0; idx < g_client_devicelist->DeviceCount; idx ++) { + if (g_client_devicelist->DeviceList[idx] != NULL && g_client_devicelist->DeviceList[idx]->DeviceId == DeviceId) { + rv = idx; + break; + } + } + TC_MUTEX_UNLOCK(mutex_client_devicelist); + } + else { + if (DeviceId < 0 || g_client_devicelist == NULL || g_client_devicelist->DeviceList == NULL || g_client_devicelist->DeviceCount < 1) { + rv = -1; + } + else for (idx = 0; idx < g_client_devicelist->DeviceCount; idx ++) { + if (g_client_devicelist->DeviceList[idx] != NULL && g_client_devicelist->DeviceList[idx]->DeviceId == DeviceId) { + rv = idx; + break; + } + } + } + + return rv; } diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/devredir.h posixrdp/posixxrdp.orig/sesman/chansrv/devredir.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/devredir.h 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/devredir.h 2010-11-08 09:56:45.000000000 +0100 @@ -2,19 +2,22 @@ #if !defined(DEVREDIR_H) #define DEVREDIR_H +#include +#include "defines.h" +#include "ntstatus.h" #include "arch.h" #include "parse.h" int APP_CC -dev_redir_init(void); +rdpdr_init(void); int APP_CC -dev_redir_deinit(void); +rdpdr_deinit(void); int APP_CC -dev_redir_data_in(struct stream* s, int chan_id, int chan_flags, int length, +rdpdr_data_in(struct stream* s, int chan_id, int chan_flags, int length, int total_length); int APP_CC -dev_redir_get_wait_objs(tbus* objs, int* count, int* timeout); +rdpdr_get_wait_objs(tbus* objs, int* count, int* timeout); int APP_CC -dev_redir_check_wait_objs(void); +rdpdr_check_wait_objs(void); #endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/drdynvc.c posixrdp/posixxrdp.orig/sesman/chansrv/drdynvc.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/drdynvc.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/drdynvc.c 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,1647 @@ +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + xrdp: A Remote Desktop Protocol server. + Copyright (C) Jay Sorg 2009 +*/ + +#include +#include +#include +#include +#include +#include + +#include "arch.h" +#include "chansrv.h" +#include "defines.h" +#include "drdynvc_defs.h" +#include "drdynvc.h" +#include "rdpdr.h" +#include "rdpdr_methods.h" +#include "os_calls.h" +#include "parse.h" +#include "trans.h" +#include "thread_calls.h" +#include "thread_macros.h" +#include "nterrmsg.h" +#include "crc32.h" + +#include "dbg.h" + +#if defined(MDBGLOG) +#undef MDBGLOG +#define MDBGLOG(...) ; +#endif + +#define RDPEDYC_NEW RDPDR_NEW + +#ifndef MAX_PENDING +#define MAX_PENDING 512 +#endif + +#ifndef WO_PATH +#define WO_PATH "xrdp_chansrv_drdynvc" +#endif + +static inline const char * nterr_msg(uint32_t); + +//static const unsigned int g_drdynvc_socket_type = WO_INET; /* 1: PF_INET/PF_INET6; 2: PF_UNIX; 3: FIFO (named pipe) */ +static const unsigned int g_drdynvc_socket_type = WO_LOCAL; /* 1: PF_INET/PF_INET6; 2: PF_UNIX; 3: FIFO (named pipe) */ +//static const unsigned int g_drdynvc_socket_type = WO_FIFO; /* 1: PF_INET/PF_INET6; 2: PF_UNIX; 3: FIFO (named pipe) */ + +static drdynvc_list_t * g_channel_list = (drdynvc_list_t *)NULL; + +static tc_t g_create_thread; +static tc_p thread_create = &g_create_thread; + +tc_p mutex_channel_list = (tc_p)NULL; +static tc_t g_channel_list_mutex; +static tc_t g_drdynvc_arr_mutex; +static tc_p mutex_drdynvc_arr = (tc_p)NULL; + +static tc_t g_cb_mutex; +static tc_p mutex_cb = (tc_p)NULL; + +static tc_t g_server_thread; +static tc_p thread_server = &g_server_thread; + +static tc_t g_data_thread; +static tc_p thread_data = &g_data_thread; +static tc_t g_data_cond; +static tc_p cond_data = (tc_p)NULL; +static tc_t g_data_mutex; +static tc_p mutex_data = (tc_p)NULL; +static tc_t g_close_mutex; +static tc_p mutex_close = (tc_p)NULL; +static tc_t g_id_mutex; +static tc_p mutex_id = (tc_p)NULL; + +static tc_t g_done_mutex; +static tc_p mutex_done = (tc_p)NULL; + +static unsigned char g_is_child = 0; +static ptrdiff_t g_idx = 0; + +static tbus * g_sck_arr = (tbus *)NULL; +static ptrdiff_t g_sck_count = 0; + +static unsigned char g_done = 0; +static unsigned char g_drdynvc_up = 0; +static tbus g_drdynvc_wait_obj = -1; +static tbus g_sck = -1; +static struct stream * g_ins = (struct stream *)NULL; +static unsigned char g_client_announce_reply_received = 0; +static int g_client_id = 0x0001; +static rdpchan_t ** g_drdynvc_arr = (rdpchan_t **)NULL; +ptrdiff_t g_drdynvc_count = 0; +static ptrdiff_t g_data_in_progress[MAX_CHANNEL]; +static ptrdiff_t g_opid = 5; +static callback_t g_callbacks[MAX_PENDING]; +static ptrdiff_t g_pending_operations[MAX_PENDING]; +static tbus g_channel_ids[MAX_CHANNEL]; + +/* static struct config_sesman * g_cfg = (struct config_sesman *)NULL; */ + +static ptrdiff_t APP_CC get_opid(void *); +static ptrdiff_t APP_CC register_opid(void *, ptrdiff_t); +static ptrdiff_t APP_CC strike_opid(void *, ptrdiff_t); +static int APP_CC opid_is_registered(void *, ptrdiff_t); +static ptrdiff_t APP_CC get_opcode_from_opid(ptrdiff_t); +static callback * APP_CC get_callback_from_opid(ptrdiff_t); + +static ptrdiff_t APP_CC reserve_channel_id(void); +static int APP_CC release_channel_id(ptrdiff_t); + +static int APP_CC drdynvc_handle_connection(tbus); + +static int APP_CC drdynvc_output_DYNVC_CREATE_REQ(struct stream *, int, const char *); +static int APP_CC drdynvc_process_CAPABILITIES_RSP(struct stream *); +static int APP_CC drdynvc_process_CREATE_RSP(struct stream *, rdpchan_t *); +static int APP_CC drdynvc_process_DATA_FIRST(struct stream *, rdpchan_t *); +static int APP_CC drdynvc_process_DATA(struct stream *, rdpchan_t *); +static int APP_CC drdynvc_process_CLOSE(struct stream *); + +static inline drdynvc_t * APP_CC get_channel(DWORD); + +static char * APP_CC ucs2ascii(const uint8_t *); + +static void * APP_CC drdynvc_data_loop(void *); +static void * APP_CC drdynvc_create_loop(void *); +static void * APP_CC drdynvc_server_loop(void *); +static ptrdiff_t APP_CC drdynvc_child_loop(ptrdiff_t); +static size_t APP_CC app_data_in(struct trans *); + +static ptrdiff_t APP_CC register_opid(void *, ptrdiff_t); +static ptrdiff_t APP_CC strike_opid(void *, ptrdiff_t); +static int APP_CC opid_is_registered(void *, ptrdiff_t); +static ptrdiff_t APP_CC get_opcode_from_opid(ptrdiff_t); +static ptrdiff_t APP_CC get_channel_index(ptrdiff_t); + +static tc_mut_t g_drdynvc_mutex; +static tc_p drdynvc_mut = (tc_p)NULL; + +extern tc_t g_out_mutex; +extern tc_p mutex_out; +extern int g_drdynvc_chan_id; /* in chansrv.c */ + +/*****************************************************************************/ +int APP_CC +drdynvc_init(void) { + int rv = 0; + int pid = 0; + char wo_fpath[512] = ""; + tbus lpid = -1; + tbus pid_handler = -1; + tbus pid_sndin = -1; + char dpath[64] = ""; + char apath[64] = ""; + + MDBGLOG("drdynvc","INFO\t[%s()]: called [%d, %d]",__func__,g_getpid(),g_gettid()); + + drdynvc_mut = (tc_p)&g_drdynvc_mutex; + tc_mutex_init(drdynvc_mut,NULL); + + { + tc_t mattr; + tc_p pattr = &mattr; + tc_t nattr; + tc_p pnattr = &nattr; + tc_t rattr; + tc_p sattr = &rattr; + TC_CONDATTR_INIT(sattr); + TC_CONDATTR_SETPSHARED(sattr, TC_PROCESS_PRIVATE); + TC_MUTATTR_INIT(pattr); + TC_MUTATTR_SETTYPE(pattr, TC_MUTEX_ERRORCHECK); + TC_MUTATTR_SETPSHARED(pattr, TC_PROCESS_SHARED); + TC_MUTATTR_INIT(pnattr); + TC_MUTATTR_SETTYPE(pnattr, TC_MUTEX_ERRORCHECK); + TC_MUTATTR_SETPSHARED(pnattr, TC_PROCESS_PRIVATE); + mutex_channel_list = &g_channel_list_mutex; + TC_MUTEX_INIT(mutex_channel_list, pattr); + mutex_drdynvc_arr = &g_drdynvc_arr_mutex; + TC_MUTEX_INIT(mutex_drdynvc_arr, pattr); + mutex_data = &g_data_mutex; + TC_MUTEX_INIT(mutex_data, pattr); + mutex_cb = &g_cb_mutex; + TC_MUTEX_INIT(mutex_cb, pattr); + mutex_done = &g_done_mutex; + TC_MUTEX_INIT(mutex_done, pattr); + mutex_close = &g_close_mutex; + TC_MUTEX_INIT(mutex_close, pattr); + mutex_id = &g_id_mutex; + TC_MUTEX_INIT(mutex_id, pattr); + cond_data = &g_data_cond; + TC_COND_CREATE(cond_data, sattr); + } + + g_memset(wo_fpath,0,sizeof(char) * 512); + TC_MUTEX_LOCK(mutex_cb); + g_memset((callback_t *)g_callbacks,0,sizeof(callback_t) * MAX_PENDING); + TC_MUTEX_UNLOCK(mutex_cb); + TC_MUTEX_LOCK(mutex_id); + g_memset(g_channel_ids,0,sizeof(g_channel_ids)); + TC_MUTEX_UNLOCK(mutex_id); + + if (g_drdynvc_up) + { + MDBGLOG("drdynvc","INFO\t[%s()]: g_drdynvc already equals 1",__func__); + return 0; + } + drdynvc_deinit(); + + /* g_cfg = (struct config_sesman *)g_malloc(sizeof(struct config_sesman), 1); */ + /* config_read(g_cfg); */ + + TC_MUTEX_LOCK(mutex_data); + g_memset(g_data_in_progress,0,sizeof(g_data_in_progress)); + TC_MUTEX_UNLOCK(mutex_data); + + /* Ascertain the PID of this process, for incorporating into the filename */ + pid = g_getpid(); + + /* Construct path and filename for the wait object */ + g_snprintf(wo_fpath,511,WO_PATH,pid); + + /* Create wait object */ + if (g_drdynvc_socket_type == WO_LOCAL || g_drdynvc_socket_type == WO_INET) { + g_drdynvc_wait_obj = g_create_wait_obj(wo_fpath); + } + else if (g_drdynvc_socket_type == WO_FIFO) { + tbus fifo_fd = -1; + fifo_fd = g_create_fifo(wo_fpath); + if (fifo_fd < 1) { + MDBGLOG("drdynvc","ERROR\t[%s()]: failed to create FIFO for wait object",__func__); + } + else { + g_drdynvc_wait_obj = g_create_wait_obj_from_fifo(fifo_fd, 0); + } + } + + if (rv == 0) { + g_drdynvc_up = 1; + make_stream(g_ins); + init_stream(g_ins, MAX_STREAM); + } + else + { + MDBGLOG("drdynvc","ERROR\t[%s()]: error on exit",__func__); + } + + MDBGLOG("drdynvc","INFO\t[%s()]: g_drdynvc_chan_id = %d",__func__,g_drdynvc_chan_id); + if (rv != 0) + { + MDBGLOG("drdynvc","INFO\t[%s()]: send_channel_data failed (rv = %d)", __func__, rv); + rv = 4; + } + + lpid = g_getpid(); + + { + tbus tsck = -1; + if (g_drdynvc_socket_type == WO_INET) { + tsck = g_tcp_socket(); + g_tcp_set_non_blocking(tsck); + if (tsck > 0 && !g_tcp_bind_flags(tsck, "7712", AI_ADDRCONFIG | AI_PASSIVE)) { + TC_MUTEX_LOCK(mutex_channel_list); + g_tcp_listen(tsck); + g_sck = g_create_wait_obj_from_socket(tsck, 1); + TC_MUTEX_UNLOCK(mutex_channel_list); + } + } + else if (g_drdynvc_socket_type == WO_LOCAL) { + int res = 0; + tsck = g_tcp_local_socket(); + if (tsck > 0) { + g_snprintf(dpath, sizeof(dpath), "%s/xrdp/.xrdp_drdynvc_sock_%d", XRDP_PID_PATH, lpid); + res = g_tcp_local_bind(tsck, dpath); + } + if (tsck < 1 || res != 0) { + MDBGLOG("drdynvc","ERROR\t[%s()]: failed to bind \"%s\" (tsck = %d, res = %d)",__func__,dpath,tsck,res); + TC_MUTEX_LOCK(mutex_close); + g_done = 1; + TC_MUTEX_UNLOCK(mutex_close); + return 0; + } + else { + TC_MUTEX_LOCK(mutex_channel_list); + g_tcp_listen(tsck); + g_sck = g_create_wait_obj_from_socket(tsck, 1); + TC_MUTEX_UNLOCK(mutex_channel_list); + } + } + else if (g_drdynvc_socket_type == WO_FIFO) { + g_snprintf(dpath, sizeof(dpath), "%s/xrdp/.xrdp_drdynvc_sock_%d", XRDP_PID_PATH, lpid); + g_create_fifo(dpath); + tsck = g_fifo_open(dpath); + if (tsck > 0) { + //TC_MUTEX_LOCK(mutex_channel_list); + //g_sck = g_create_wait_object_from_fifo(tsck, 0); + //TC_MUTEX_UNLOCK(mutex_channel_list); + } + } + if (g_sck > 0) { + } + } + + TC_THREAD_INIT(&(thread_data->thread), drdynvc_data_loop, NULL); + TC_THREAD_INIT(&(thread_create->thread), drdynvc_create_loop, NULL); + //TC_THREAD_INIT(&(thread_server->thread), drdynvc_server_loop, NULL); + + if ((pid_handler = g_fork()) < 0) { + MDBGLOG("drdynvc","ERROR\t[%s()]: g_fork() failed (pid_handler = %d)",__func__,pid_handler); + rv = -1; + goto end; + } + else if (pid_handler == 0) { /* child */ + tbus hpid = -1; + hpid = g_getpid(); + g_snprintf(apath, sizeof(apath), "%s/xrdp/audio_interface_socket_%d", XRDP_PID_PATH, hpid); + if ((pid_sndin = g_fork()) < 0) { + MDBGLOG("drdynvc","ERROR\t[%s()]: g_fork() failed (pid_sndin = %d)",__func__,pid_sndin); + rv = -1; + goto end; + } + else if (pid_sndin == 0) { + unsigned char lcnt = 0; + char * cargs[] = { "xrdp_rdpeai", apath, (char *)NULL }; + char exe_path[256] = ""; + g_memset(exe_path,0,sizeof(exe_path)); + g_snprintf(exe_path, sizeof(exe_path), "%s/xrdp_rdpeai", XRDP_SBIN_PATH); + if (g_strlen(apath) > 0) while (!g_file_exist(apath) && lcnt < 11) { + lcnt++; + g_sleep(600); + } + if (g_strlen(apath) > 0 && lcnt < 10) { + if (g_strlen(exe_path) > 0) { + MDBGLOG("drdynvc","INFO\t[%s()]: launching \"%s(%s)\"...",__func__,exe_path,apath); + g_execvp(exe_path, cargs); + MDBGLOG("drdynvc","ERROR\t[%s()]: g_execvp() failed (exe_path = %s)",__func__,exe_path); + rv = -1; + } + else { + MDBGLOG("drdynvc","ERROR\t[%s()]: exe_path does not exist (exe_path = \"%s\")",__func__,exe_path); + rv = -1; + } + } + else { + MDBGLOG("drdynvc","ERROR\t[%s()]: socket file does not exist (apath = \"%s\")",__func__,apath); + rv = -1; + } + } + else { + char * cargs[] = { "xrdp_drdynvc_interface", dpath, apath, (char *)NULL }; + char exe_path[256] = ""; + g_memset(exe_path,0,sizeof(exe_path)); + g_snprintf(exe_path, sizeof(exe_path), "%s/xrdp_drdynvc_interface", XRDP_SBIN_PATH); + if (g_strlen(exe_path) > 0) { + MDBGLOG("drdynvc","INFO\t[%s()]: launching \"%s(%s, %s)\"...",__func__,exe_path,dpath,apath); + g_execvp(exe_path, cargs); + MDBGLOG("drdynvc","ERROR\t[%s()]: g_execvp() failed (exe_path = %s)",__func__,exe_path); + rv = -1; + } + else { + MDBGLOG("drdynvc","ERROR\t[%s()]: exe_path does not exist (exe_path = \"%s\")",__func__,exe_path); + rv = -1; + } + } + } + end:; + return rv; +} + +/*****************************************************************************/ +void * APP_CC +drdynvc_create_loop(void * arg) { + void * rv = (void *)NULL; + ptrdiff_t size = 0; + DYNVC_CAPS_VERSION2 * pdu = (DYNVC_CAPS_VERSION2 *)NULL; + LOCAL_STREAM(s); + LOCAL_STREAM(ts); + + pdu = RDPEDYC_NEW(DYNVC_CAPS_VERSION2); + pdu->Version = DRDYNVC_VERSION2; + pdu->out(pdu, s); + s_mark_end(s); + size = s->end - s->data; + //g_hexdump_file("/tmp/taskq_DYNVC_CAPS_VERSION2.hexdump",s->data,size); + MDBGLOG("drdynvc","INFO\t[%s()]: data out, sending (chan_id = %d)",__func__,g_drdynvc_chan_id); + TC_MUTEX_LOCK(mutex_out); + send_channel_data(g_drdynvc_chan_id, s->data, size); + TC_MUTEX_UNLOCK(mutex_out); + + TC_THREAD_EXIT(NULL); + return rv; +} + +/*****************************************************************************/ +int APP_CC +drdynvc_deinit(void) { + ptrdiff_t idx = 0; + + MDBGLOG("drdynvc","INFO\t[%s()]: called",__func__); + + if (g_drdynvc_wait_obj > -1) { + g_delete_wait_obj(g_drdynvc_wait_obj); + } + + g_drdynvc_up = 0; + g_drdynvc_wait_obj = -1; + g_client_id = 0x0001; + + if (g_ins != NULL) { + //free_stream(g_ins); + g_ins = (struct stream *)NULL; + } + + TC_MUTEX_LOCK(mutex_drdynvc_arr); + if (g_drdynvc_arr != NULL && g_drdynvc_count > 0) { + for (idx = 0; idx < g_drdynvc_count; idx++) { + if (g_drdynvc_arr[idx] != NULL) { + if (g_drdynvc_arr[idx]->pid > 0) { + g_waitpid(g_drdynvc_arr[idx]->pid); + } + g_free(g_drdynvc_arr[idx]); + } + } + } + TC_MUTEX_UNLOCK(mutex_drdynvc_arr); + + + return 0; +} + +/*****************************************************************************/ +int APP_CC drdynvc_data_in(struct stream * s, int chan_id, int chan_flags, int length, int total_length) { + int rv = 0; + ptrdiff_t idx = 0; + struct stream * ls = (struct stream *)NULL; + drdynvc_t * channel = (drdynvc_t *)NULL; + struct trans * trans = (struct trans *)NULL; + + MDBGLOG("drdynvc","INFO\t[%s()]: called (chan_id = 0x%8.8x; chan_flags = 0x%8.8x; length = %d; total_length = %d) [%d, %d]", __func__, chan_id, chan_flags, length, total_length, g_getpid(), g_gettid()); + + if (chan_flags == 0x00000000) { + } + else if ((chan_flags & 3) == chan_flags) + { + ls = s; + } + else + { + if (chan_flags & 1) + { + init_stream(g_ins, total_length) + } + in_uint8a(s, g_ins->end, length); + g_ins->end += length; + if ((chan_flags & 2) == 0) + { + MDBGLOG("drdynvc","INFO\t[%s()]: exiting",__func__); + rv = 0; + goto exit; + } + else { + ls = g_ins; + } + } + + //g_hexdump_file("/tmp/taskq_drdynvc_data_in.hexdump",ls->data,(ls->end - ls->data)); + + if (g_channel_list != NULL && g_channel_list->ChannelCount > 0) + for (idx = (MAX_CHANNEL - 1); idx > -1; idx--) if (g_channel_list->ChannelList[idx] != NULL && g_channel_list->ChannelList[idx]->initialized == 1 && g_channel_list->ChannelList[idx]->ccon != NULL && g_channel_list->ChannelList[idx]->ccon->sck > -1) { + if (g_channel_list->ChannelList[idx]->ccon != NULL) { + channel = g_channel_list->ChannelList[idx]; + trans = channel->ccon; + // MDBGLOG("drdynvc","DEBUG\t[%s()]: channel->channel_id=%d; channel->index=%d",__func__,channel->channel_id,channel->index); + break; + } + } + + { + uint8_t cmd = 0x00; + union { + BYTE val; + DYNVC_HEADER hdr; + } tmp; + DYNVC_HEADER * hdr = &(tmp.hdr); + + g_memset(hdr,0,sizeof(DYNVC_HEADER)); + g_memcpy(hdr,ls->p,sizeof(DYNVC_HEADER)); + + cmd = (hdr->Cmd & 0xf0) >> 4; + + switch (cmd) { + case DRDYNVC_CAPABILITIES: + MDBGLOG("drdynvc","INFO\t[%s()]: hdr->Cmd = 0x%8.8x (DRDYNVC_CAPABILITIES)",__func__,hdr->Cmd); + rv = drdynvc_process_CAPABILITIES_RSP(ls); + break; + case DRDYNVC_CREATE: + MDBGLOG("drdynvc","INFO\t[%s()]: hdr->Cmd = 0x%8.8x (DRDYNVC_CREATE)",__func__,hdr->Cmd); + rv = drdynvc_process_CREATE_RSP(ls, channel); + break; + case DRDYNVC_DATAFIRST: + MDBGLOG("drdynvc","INFO\t[%s()]: hdr->Cmd = 0x%8.8x (DRDYNVC_DATAFIRST)",__func__,hdr->Cmd); + rv = drdynvc_process_DATA_FIRST(ls, channel); + break; + case DRDYNVC_DATA: + MDBGLOG("drdynvc","INFO\t[%s()]: hdr->Cmd = 0x%8.8x (DRDYNVC_DATA)",__func__,hdr->Cmd); + rv = drdynvc_process_DATA(ls, channel); + break; + case DRDYNVC_CLOSE: + MDBGLOG("drdynvc","INFO\t[%s()]: hdr->Cmd = 0x%8.8x (DRDYNVC_CLOSE)",__func__,hdr->Cmd); + rv = drdynvc_process_CLOSE(ls); + break; + default: + MDBGLOG("drdynvc", "WARNING\t[%s()]: unknown opcode (cmd = 0x%8.8x; hdr->Cmd = 0x%8.8x)", __func__, cmd, hdr->Cmd); + break; + } + } + + exit:; + return rv; +} + +/*****************************************************************************/ +int APP_CC +drdynvc_get_wait_objs(tbus * objs, int * count, int * timeout) { + int rv = 0; + ptrdiff_t lcount = 0; + ptrdiff_t idx = 0; + tbus sck = -1; + + if ((g_drdynvc_up == 0) || (objs == NULL) || (count == NULL) || g_is_child > 0) + { + MDBGLOG("drdynvc","ERROR\t[%s()]: exiting (g_drdynvc_up = %d, objs = %p, count = %d, g_is_child = %d)",__func__,g_drdynvc_up,objs,*count,g_is_child); + rv = -1; + } + else if (g_drdynvc_wait_obj < 1) { + MDBGLOG("drdynvc","WARNING\t[%s()]: g_drdynvc_wait_obj is not set",__func__); + rv = -1; + } + else { + lcount = *count; + objs[lcount] = g_drdynvc_wait_obj; + lcount++; + TC_MUTEX_LOCK(mutex_channel_list); + if (g_sck < 0) { + TC_MUTEX_UNLOCK(mutex_channel_list); + MDBGLOG("drdynvc","INFO\t[%s()]: g_sck not yet assigned...",__func__); + g_sleep(500); + TC_MUTEX_LOCK(mutex_channel_list); + } + if (g_sck > -1) { + objs[lcount] = g_sck; + lcount++; + } + else { + MDBGLOG("drdynvc","WARNING\t[%s()]: g_sck still not yet assigned",__func__); + } + *count = lcount; + if (g_channel_list != NULL && g_channel_list->ChannelCount > 0) + for (idx = 0; idx < MAX_CHANNEL; idx++) if (g_channel_list->ChannelList[idx] != NULL && g_channel_list->ChannelList[idx]->initialized > 0 && g_channel_list->ChannelList[idx]->ccon != NULL && g_channel_list->ChannelList[idx]->ccon->sck > 0) { + //drdynvc_t * channel = get_channel(idx); + drdynvc_t * channel = g_channel_list->ChannelList[idx]; + if (channel != NULL && channel->initialized > 0 && channel->ccon != NULL && channel->ccon->sck > 0) { + //MDBGLOG("drdynvc","INFO\t[%s()]: adding socket %d",__func__,channel->ccon->sck); + //trans_get_wait_objs(channel->ccon, objs, count, NULL); + objs[lcount] = channel->ccon->sck; + lcount++; + *count = lcount; + } + else if (!(channel = get_channel(idx)) && channel != NULL && channel->initialized > 0 && channel->ccon != NULL && channel->ccon->sck > 0) { + objs[lcount] = channel->ccon->sck; + lcount++; + *count = lcount; + } + else { + MDBGLOG("drdynvc","ERROR\t[%s()]: unable to ascertain socket (channel = %p)",__func__,channel); + } + /* + if (sck > 0) { + lcount = *count; + objs[lcount] = sck; + lcount++; + *count = lcount; + } + */ + } + TC_MUTEX_UNLOCK(mutex_channel_list); + } + + return rv; +} + +/*****************************************************************************/ +int APP_CC +drdynvc_check_wait_objs(void) { + int rv = 0; + ptrdiff_t idx = 0; + + if (!g_drdynvc_up || g_is_child > 0) { + rv = -1; + } + else { + TC_MUTEX_LOCK(mutex_channel_list); + if (g_is_wait_obj_set(g_drdynvc_wait_obj)) { + } + if (g_sck > -1 && g_is_wait_obj_set(g_sck)) { + TC_MUTEX_UNLOCK(mutex_channel_list); + drdynvc_handle_connection(g_sck); + TC_MUTEX_LOCK(mutex_channel_list); + } + if (g_channel_list != NULL && g_channel_list->ChannelCount > 0 && g_channel_list->ChannelList != NULL) { + for (idx = 0; idx < MAX_CHANNEL; idx++) if (g_channel_list->ChannelList != NULL && g_channel_list->ChannelList[idx] != NULL && g_channel_list->ChannelList[idx]->initialized > 0 && g_channel_list->ChannelList[idx]->ccon != NULL && g_channel_list->ChannelList[idx]->ccon->sck > -1) { + drdynvc_t * channel = g_channel_list->ChannelList[idx]; + if (channel == NULL) { + channel = get_channel(idx); + } + if (channel == NULL) { + MDBGLOG("drdynvc","ERROR\t[%s()]: NULL pointer (idx = %d)",__func__,idx); + } + else { + struct trans * ccon = (struct trans *)NULL; + ccon = channel->ccon; + /* handle any inbound replies from the child: */ + if (ccon == NULL) { + MDBGLOG("drdynvc","ERROR\t[%s()]: ccon is NULL",__func__); + } + else if (trans_check_wait_objs(ccon) != 0) { + rv = -1; + } + } + } + } + TC_MUTEX_UNLOCK(mutex_channel_list); + } + return rv; +} + +/*************************************************************************/ +/*************************************************************************/ + +static int APP_CC +drdynvc_output_DYNVC_CREATE_REQ(struct stream * s, int ChannelId, const char * ChannelName) { + int rv = 0; + DYNVC_ANY pdu; + DYNVC_CREATE_REQ * req = (DYNVC_CREATE_REQ *)(&(pdu.create_req)); + + MDBGLOG("drdynvc","INFO\t[%s()]: called [%d, %d]",__func__,g_getpid(),g_gettid()); + + g_memset(&req, 0, sizeof(DYNVC_CREATE_REQ)); + + construct_DYNVC_CREATE_REQ(req); + req->ChannelId = ChannelId; + g_strncpy(req->ChannelName, ChannelName, 48); + req->cbChId = DRDYNVC_BYTE; + send_DYNVC_CREATE_REQ(req, s); + + MDBGLOG("drdynvc","INFO\t[%s()]: done.",__func__); + return rv; +} + + +/*****************************************************************************/ +static size_t APP_CC +app_data_in(struct trans * trans) { + struct stream * s = (struct stream *)NULL; + char odata[MAX_STREAM]; + struct stream os; + char qdata[MAX_STREAM]; + struct stream qs; + char tdata[MAX_STREAM]; + struct stream ts; + struct stream * r = (struct stream *)NULL; + struct stream * q = (struct stream *)NULL; + struct stream * l = (struct stream *)NULL; + callback_t * cb = (callback_t *)NULL; + ptrdiff_t fpath_length = 0; + ptrdiff_t size = 0; + ptrdiff_t len = 0; + ptrdiff_t idx = 0; + int rdpchan_opcode = 0; + int error = 0; + ptrdiff_t opid = 0; + int uniqid = 0; + uint32_t tsize = 0x00000000; + uint32_t calc_crc32 = 0x00000000; + uint32_t crc32 = 0x00000000; + uint32_t magic = 0x00000000; + uint32_t channel_id = 0x00000000; + void * pdu = (void *)NULL; + BYTE * buf = (BYTE *)NULL; + DYNVC_ANY item; + + MDBGLOG("drdynvc","INFO\t[%s()]: called",__func__); + + g_memset(&item,0,sizeof(DYNVC_ANY)); + + if (trans == 0) { + return 0; + } + + g_memset((char *)tdata,0,sizeof(char)*MAX_STREAM); + g_memset(&ts,0,sizeof(struct stream)); + ts.data = (char *)tdata; + ts.p = ts.data; + ts.end = ts.data; + ts.size = MAX_STREAM; + r = &ts; + g_memset((char *)qdata,0,sizeof(char)*MAX_STREAM); + g_memset(&qs,0,sizeof(struct stream)); + qs.data = (char *)qdata; + qs.p = qs.data; + qs.end = qs.data; + qs.size = MAX_STREAM; + q = &qs; + g_memset((char *)odata,0,sizeof(char)*MAX_STREAM); + g_memset(&os,0,sizeof(struct stream)); + os.data = (char *)odata; + os.p = os.data; + os.end = os.data; + os.size = MAX_STREAM; + l = &os; + + s = (struct stream *)trans_get_in_s(trans); + g_memcpy(l->data,s->data,s->size); + l->size = s->size; + if ((s->p - s->data) > 0) { + l->p += (s->p - s->data); + } + if ((s->end - s->data) > 0) { + l->end = l->data + (s->end - s->data); + } + g_memcpy(q->data,s->data,s->size); + q->size = s->size; + if ((s->p - s->data) > 0) { + q->p += (s->p - s->data); + } + if ((s->end - s->data) > 0) { + q->end = q->data + (s->end - s->data); + } + in_uint32_le(q, magic); + in_uint32_le(q, rdpchan_opcode); + in_uint32_le(q, size); + in_uint32_le(q, channel_id); + in_uint32_le(q, uniqid); + in_uint32_le(q, crc32); + + MDBGLOG("drdynvc","DEBUG\t[%s()]: size = %d; magic = 0x%8.8x (should be 0x%8.8x); rdpchan_opcode = 0x%8.8x",__func__,size,magic,RDP_PACKET_MAGIC,rdpchan_opcode); + + if (size > 0) { + char * p = (char *)NULL; + size_t tlen = size; + trans_force_read(trans, tlen); + s->p += 24; + if ((rdpchan_opcode == RDPCHAN_DATAFIRST) || ((rdpchan_opcode & RDPCHAN_DATAFIRST) == rdpchan_opcode && rdpchan_opcode != 0x0000)) { + in_uint32_le(s, tsize); + tlen -= 4; + } + p = s->p; + if (tlen > 0) { + buf = (BYTE *)g_malloc(sizeof(BYTE) * tlen, 1); + in_uint8a(s, (char *)buf, tlen); + } + calc_crc32 = Crc32_ComputeBuf(0, p, tlen); + MDBGLOG("drdynvc", "INFO\t[%s()]: crc32 = 0x%8.8x, calc_crc32 = 0x%8.8x", __func__, crc32, calc_crc32); + len = tlen; + } + + MDBGLOG("drdynvc","INFO\t[%s()]: ** rdpchan_opcode = 0x%8.8x; size = %d; uniqid = %d; buf = \"%s\"; tsize = %d",__func__,rdpchan_opcode,size,uniqid,(char *)buf,tsize); + + make_stream(r); + init_stream(r, MAX_STREAM); + + if (error == 0) { + unsigned char found = 0; + TC_MUTEX_LOCK(mutex_cb); + for (opid = 4; opid < MAX_PENDING; opid++) { + if (g_callbacks[opid].opid < 1) { + found = 1; + break; + } + } + if (found > 0) { + g_memset((callback_t *)(&(g_callbacks[opid])), 0, sizeof(callback)); + g_callbacks[opid].opid = opid; + g_callbacks[opid].type = 1; + g_callbacks[opid].channel = trans->callback_data; + g_callbacks[opid].opcode = rdpchan_opcode; + g_callbacks[opid].CompletionId = opid; + g_callbacks[opid].trans = trans; + g_callbacks[opid].uniqid = uniqid; + cb = &(g_callbacks[opid]); + } + if (found < 1) { + MDBGLOG("drdynvc","ERROR\t[%s()]: unable to allocate callback slot (opcode = %8.8x; opid = %d)",__func__,rdpchan_opcode,opid); + error = -1; + } + else if (cb == NULL) { + MDBGLOG("drdynvc","ERROR\t[%s()]: failed to assign callback to operation (opcode = %8.8x; opid = %d)",__func__,rdpchan_opcode,opid); + error = -1; + } + else { + switch(rdpchan_opcode) { + case RDPCHAN_OPEN: + MDBGLOG("drdynvc","INFO\t[%s()]: opcode = RDPCHAN_OPEN",__func__); + { + DYNVC_CREATE_REQ * pdu = &(item.create_req); + construct_DYNVC_CREATE_REQ(pdu); + pdu->ChannelId = cb->channel->channel_id; + g_strncpy(pdu->ChannelName, buf, 48); + pdu->cbChId = DRDYNVC_BYTE; + if (pdu->out == NULL) { + MDBGLOG("drdynvc","ERROR\t[%s()]: pdu->out() is NULL",__func__); + } + else { + pdu->out(pdu, r); + } + } + break; + case RDPCHAN_CLOSE: + MDBGLOG("drdynvc","INFO\t[%s()]: opcode = RDPCHAN_CLOSE",__func__); + { + DYNVC_CLOSE * pdu = &(item.close); + construct_DYNVC_CLOSE(pdu); + pdu->ChannelId = cb->channel->channel_id; + if (pdu->out == NULL) { + MDBGLOG("drdynvc","ERROR\t[%s()]: pdu->out() is NULL",__func__); + } + else { + pdu->out(pdu, r); + } + } + break; + case RDPCHAN_DATAFIRST: + MDBGLOG("drdynvc","INFO\t[%s()]: opcode = RDPCHAN_DATAFIRST",__func__); + { + DYNVC_DATA_FIRST * pdu = &(item.datafirst); + construct_DYNVC_DATA_FIRST(pdu); + pdu->ChannelId = cb->channel->channel_id; + if (pdu->out == NULL) { + MDBGLOG("drdynvc","ERROR\t[%s()]: pdu->out() is NULL",__func__); + } + else { + if (len > 0) { + pdu->Length = len; + g_memcpy(pdu->Data, buf, len); + } + pdu->out(pdu, r); + } + } + break; + case RDPCHAN_DATA: + MDBGLOG("drdynvc","INFO\t[%s()]: opcode = RDPCHAN_DATA",__func__); + { + //DYNVC_DATA * pdu = &(item.data); + DYNVC_DATA * pdu = (DYNVC_DATA *)NULL; + pdu = (DYNVC_DATA *)g_malloc(sizeof(DYNVC_DATA) + len, 1); + construct_DYNVC_DATA(pdu); + pdu->Sp = 0x01; + pdu->ChannelId = cb->channel->channel_id; + if (pdu->out == NULL) { + MDBGLOG("drdynvc","ERROR\t[%s()]: pdu->out() is NULL",__func__); + } + else { + if (len > 0) { + pdu->Length = len; + g_memcpy(pdu->Data, buf, len); + } + pdu->out(pdu, r); + } + } + break; + case RDPCHAN_QUERY: + MDBGLOG("drdynvc","INFO\t[%s()]: opcode = RDPCHAN_QUERY",__func__); + { + } + break; + default: + MDBGLOG("drdynvc","ERROR\t[%s()]: unrecognized opcode (0x%8.8x)",__func__,rdpchan_opcode); + free_stream(r); + r = (struct stream *)NULL; + r = trans_get_out_s(trans, MAX_STREAM); + magic = RDP_PACKET_MAGIC; + crc32 = 0x00000000; + size = 0x00000000; + out_uint32_le(r, magic); + out_uint32_le(r, RDPCHAN_ERROR); + out_uint32_le(r, size); + out_uint32_le(r, channel_id); + out_uint32_le(r, uniqid); + out_uint32_le(r, crc32); + s_mark_end(r); + trans_force_write(trans); + r->end = r->data; + break; + } + /* send the assembled PDU to the RDP client: */ + s_mark_end(r); + size = r->end - r->data; + if (size > 0) { + TC_MUTEX_LOCK(mutex_out); + error = send_channel_data(g_drdynvc_chan_id, r->data, size); + TC_MUTEX_UNLOCK(mutex_out); + //g_hexdump_file("/tmp/taskq_hex_rdata.hexdump",r->data,size); + MDBGLOG("drdynvc","INFO\t[%s()]: sent channel data (size = %d)",__func__,size); + g_memset(r->data,0,MAX_STREAM); + free_stream(r); + } + else { + MDBGLOG("drdynvc","ERROR\t[%s()]: output PDU is empty (size == 0)",__func__); + } + } + TC_MUTEX_UNLOCK(mutex_cb); + } + return error; +} + + +/*****************************************************************************/ +static ptrdiff_t APP_CC get_channel_index(ptrdiff_t ChannelId) { + ptrdiff_t rv = -1; + ptrdiff_t idx = 0; + + if (TC_MUTEX_TRYLOCK(mutex_channel_list) == 0) { + if (ChannelId < 0 || g_channel_list == NULL || g_channel_list->ChannelList == NULL || g_channel_list->ChannelCount < 1) { + rv = -1; + } + else for (idx = 0; idx < g_channel_list->ChannelCount; idx ++) { + if (g_channel_list->ChannelList[idx] != NULL && g_channel_list->ChannelList[idx]->channel_id == ChannelId) { + rv = idx; + break; + } + } + TC_MUTEX_UNLOCK(mutex_channel_list); + } + else { + if (ChannelId < 0 || g_channel_list == NULL || g_channel_list->ChannelList == NULL || g_channel_list->ChannelCount < 1) { + rv = -1; + } + else for (idx = 0; idx < g_channel_list->ChannelCount; idx ++) { + if (g_channel_list->ChannelList[idx] != NULL && g_channel_list->ChannelList[idx]->channel_id == ChannelId) { + rv = idx; + break; + } + } + } + + return rv; +} + +/*****************************************************************************/ +static int APP_CC drdynvc_process_CAPABILITIES_RSP(struct stream * s) { + int rv = 0; + char * tp = (char *)(s->p); + DYNVC_CAPS_RSP * creply = (DYNVC_CAPS_RSP *)NULL; + creply = RDPEDYC_NEW(DYNVC_CAPS_RSP); + get_DYNVC_CAPS_RSP(creply, s); + //g_hexdump_file("/tmp/taskq_hex_DYNVC_CAPS_RSP.hexdump",tp,(s->end - tp)); + g_client_announce_reply_received = 1; + return rv; +} + +/*****************************************************************************/ +static int APP_CC drdynvc_process_CREATE_RSP(struct stream * s, rdpchan_t * chan) { + int rv = 0; + uint32_t * ures = (uint32_t *)NULL; + int32_t * res = (int32_t *)NULL; + char * tp = (char *)(s->p); + DYNVC_CREATE_RSP * creply = (DYNVC_CREATE_RSP *)NULL; + struct trans * trans = (struct trans *)NULL; + trans = chan->ccon; + creply = RDPEDYC_NEW(DYNVC_CREATE_RSP); + get_DYNVC_CREATE_RSP(creply, s); + res = (int32_t *)(&(creply->CreationStatus)); + ures = (uint32_t *)(&(creply->CreationStatus)); + MDBGLOG("drdynvc","INFO\t[%s()]: CreationStatus = 0x%8.8x (\"%s\", ChannelId = %d)",__func__,(*ures),(((*res) < 0)?nterr_msg((*ures)):"OK"),creply->ChannelId); + //g_hexdump_file("/tmp/taskq_hex_DYNVC_CREATE_RSP.hexdump",tp,(s->end - tp)); + chan->dynamic_channel_index = creply->ChannelId; + if (trans == NULL) { + MDBGLOG("drdynvc","ERROR\t[%s()]: trans is NULL",__func__); + } + else if (g_channel_list != NULL && g_channel_list->ChannelList != NULL && g_channel_list->ChannelCount > 0) { + struct stream * r = (struct stream *)NULL; + r = trans_get_out_s(trans, MAX_STREAM); + //out_uint32_t(r, *ures); + if (*ures == 0x00000000) { + const char rmsg[] = "OK\n"; + char dmsg[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + g_snprintf(dmsg, (sizeof(dmsg) - 1), "%d", creply->ChannelId); + out_uint8a(r, rmsg, 3); + out_uint8a(r, dmsg, g_strlen(dmsg)); + out_uint8(r, '\n'); + } + else { + const char rmsg[] = "ERROR\n"; + out_uint8a(r, rmsg, 6); + } + s_mark_end(r); + r->p = r->data; + trans_force_write(trans); + //r->p = r->end = r->data; + } + end:; + MDBGLOG("drdynvc","INFO\t[%s()]: done.",__func__); + return rv; +} + +/*****************************************************************************/ +static int APP_CC OLD_drdynvc_process_DATA_FIRST(struct stream * s, rdpchan_t * ichan) { + int rv = 0; + ptrdiff_t idx = -1; + char * tp = (char *)NULL; + char * cp = (char *)NULL; + DYNVC_DATA_FIRST * dp = (DYNVC_DATA_FIRST *)NULL; + DYNVC_DATA_FIRST * cdata = (DYNVC_DATA_FIRST *)NULL; + if (s == NULL || ichan == NULL || s->p == NULL) { + rv = -1; + goto end; + } + dp = (DYNVC_DATA_FIRST *)(s->p); + cdata = RDPEDYC_NEW(DYNVC_DATA_FIRST); + tp = s->p; + cp = (char *)(dp->Data); + get_DYNVC_DATA_FIRST(cdata, s); + idx = cdata->ChannelId; + if (idx > -1 && idx < MAX_CHANNEL && idx < g_drdynvc_count) { + drdynvc_t * chan = (drdynvc_t *)NULL; + struct stream * qs = (struct stream *)NULL; + DECLARE_SQ(tmp); + chan = get_channel(idx); + cp = cdata->Data; + TC_MUTEX_LOCK(mutex_data); + g_data_in_progress[idx] = 1; + TC_MUTEX_LOCK(&(chan->ilock)); + chan->istatus = 1; + chan->ilen = cdata->Length; + chan->irem = chan->ilen; + if (chan->ilen == 0 || cp == NULL) { + chan->ilen = 0; + chan->irem = 0; + chan->ihead = (stream_list_t *)NULL; + chan->istatus = 0; + } + else if (s->p > cp && tmp != NULL) { + size_t tlen = (s->p > cp) ? (s->p - cp) : 0; + make_stream(qs); + init_stream(qs,tlen); + g_memcpy(qs->data,cp,tlen); + tmp->s = qs; + SQ_ENQ(chan->ihead, tmp); + chan->irem -= tlen; + TC_COND_SIGNAL(cond_data); + { + tc_t tattr; + tc_p pattr = &tattr; + g_memset(pattr,0,sizeof(tc_t)); + TC_CONDATTR_INIT(pattr); + TC_CONDATTR_SETPSHARED(pattr, TC_PROCESS_PRIVATE); + TC_COND_CREATE(cond_data, pattr); + } + } + TC_MUTEX_UNLOCK(&(chan->ilock)); + TC_MUTEX_UNLOCK(mutex_data); + } + end:; + return rv; +} + +/*****************************************************************************/ +static int APP_CC drdynvc_process_DATA_FIRST(struct stream * s, rdpchan_t * ichan) { + int rv = 0; + if (s == NULL || s->data == NULL || s->p == NULL || s->end == NULL || s->end <= s->p) { + MDBGLOG("drdynvc","ERROR\t[%s()]: stream \"s\" is NULL",__func__); + rv = -1; + } + else { + int pres = 0; + uint8_t z = 0; + ptrdiff_t idx = -1; + unsigned char in_progress = 0; + char * tp = (char *)NULL; + char * cp = (char *)NULL; + DYNVC_DATA_FIRST * dp = (DYNVC_DATA_FIRST *)NULL; + DYNVC_DATA_FIRST * cdata = (DYNVC_DATA_FIRST *)NULL; + struct trans * trans = (struct trans *)NULL; + s->p = s->data; + s->p += 4; + cdata = (DYNVC_DATA_FIRST *)g_malloc((sizeof(DYNVC_DATA_FIRST) + (s->end - s->p)), 1); + construct_DYNVC_DATA_FIRST(cdata); + in_uint32_le(s, cdata->Length); + tp = s->p; + MDBGLOG("drdynvc","INFO\t[%s()]: cdata->Length = %d",__func__,cdata->Length); + if (ichan == NULL) { + MDBGLOG("drdynvc","ERROR\t[%s() @ %d]: invalid channel",__func__,__LINE__); + rv = -1; + goto exit; + } + else { + ptrdiff_t tlen = 0; + struct stream * r = (struct stream *)NULL; + drdynvc_t * chan = (drdynvc_t *)NULL; + chan = ichan; + if (chan == NULL) { + MDBGLOG("drdynvc","ERROR\t[%s() @ %d]: chan is NULL",__func__,__LINE__); + rv = -1; + goto exit; + } + idx = cdata->ChannelId; + cp = cdata->Data; + tlen = cdata->Length; + if (tlen < 1) { + MDBGLOG("drdynvc","ERROR\t[%s() @ %d]: tlen is empty",__func__,__LINE__); + rv = -1; + goto exit; + } + else if (tlen > MAX_STREAM) { + MDBGLOG("drdynvc","ERROR\t[%s() @ %d]: too much data (tlen = %d)",__func__,__LINE__,tlen); + rv = -1; + goto exit; + } + trans = chan->ccon; + TC_MUTEX_LOCK(mutex_data); + g_data_in_progress[idx] = 1; + { + struct stream * qs = (struct stream *)NULL; + DECLARE_SQ(tmp); + make_stream(qs); + init_stream(qs,tlen); + g_memcpy(qs->data,cp,tlen); + tmp->s = qs; + TC_MUTEX_LOCK(&(chan->ilock)); + chan->istatus = 1; + chan->ilen = cdata->Length; + chan->irem = chan->ilen - tlen; + SQ_ENQ(chan->ihead, tmp); + TC_COND_SIGNAL(cond_data); + { + tc_t tattr; + tc_p pattr = &tattr; + g_memset(pattr,0,sizeof(tc_t)); + TC_CONDATTR_INIT(pattr); + TC_CONDATTR_SETPSHARED(pattr, TC_PROCESS_PRIVATE); + TC_COND_CREATE(cond_data, pattr); + } + TC_MUTEX_UNLOCK(&(chan->ilock)); + TC_MUTEX_UNLOCK(mutex_data); + } + } + } + exit:; + return rv; +} + +/*****************************************************************************/ +static int APP_CC drdynvc_process_DATA(struct stream * s, rdpchan_t * ichan) { + int rv = 0; + if (s == NULL || s->data == NULL || s->p == NULL || s->end == NULL || s->end <= s->p) { + MDBGLOG("drdynvc","ERROR\t[%s()]: stream \"s\" is NULL",__func__); + rv = -1; + } + else { + ptrdiff_t idx = -1; + unsigned char in_progress = 0; + char * tp = (char *)NULL; + char * cp = (char *)NULL; + DYNVC_DATA * dp = (DYNVC_DATA *)(s->p); + DYNVC_DATA * cdata = (DYNVC_DATA *)NULL; + struct trans * trans = (struct trans *)NULL; + cdata = (DYNVC_DATA *)g_malloc((sizeof(DYNVC_DATA) + (s->end - s->p)), 1); + tp = s->p; + cp = (char *)(dp->Data); + cdata->Length = (DWORD)(s->end - s->p); + if (cdata->Length > 0) { + g_memcpy(cdata->Data, s->p, cdata->Length); + } + if (ichan == NULL) { + MDBGLOG("drdynvc","ERROR\t[%s() @ %d]: invalid channel",__func__,__LINE__); + rv = -1; + goto exit; + } + else { + ptrdiff_t tlen = 0; + struct stream * r = (struct stream *)NULL; + drdynvc_t * chan = (drdynvc_t *)NULL; + chan = ichan; + if (chan == NULL) { + MDBGLOG("drdynvc","ERROR\t[%s() @ %d]: chan is NULL",__func__,__LINE__); + rv = -1; + goto exit; + } + cp = cdata->Data; + tlen = cdata->Length; + if (tlen < 1) { + MDBGLOG("drdynvc","ERROR\t[%s() @ %d]: tlen is empty",__func__,__LINE__); + rv = -1; + goto exit; + } + else if (tlen > MAX_STREAM) { + MDBGLOG("drdynvc","ERROR\t[%s() @ %d]: too much data (tlen = %d)",__func__,__LINE__,tlen); + rv = -1; + goto exit; + } + trans = chan->ccon; + idx = cdata->ChannelId; + TC_MUTEX_LOCK(mutex_data); + in_progress = g_data_in_progress[idx]; + if (1 || !in_progress) { + unsigned char tlocked = 0; + if (trans != NULL && trans->lock != NULL) { + TC_MUTEX_LOCK(trans->lock); + trans->locked = 1; + tlocked = 1; + } + r = trans_get_out_s(trans, tlen); + if (r == NULL || r->data == NULL || r->size < tlen) { + if (tlocked) { + trans->locked = 0; + TC_MUTEX_UNLOCK(trans->lock); + tlocked = 0; + } + MDBGLOG("drdynvc","ERROR\t[%s() @ %d]: r is NULL or invalid",__func__,__LINE__); + rv = -1; + goto exit; + } + else { + out_uint8a(r, cp, tlen); + s_mark_end(r); + MDBGLOG("drdynvc","INFO\t[%s() @ %d]: about to call trans_force_write() [trans->sck = %d; tlen = %d; r->end - r->data = %d]:",__func__,__LINE__,trans->sck,tlen,(r->end - r->data)); + trans_force_write(trans); + MDBGLOG("drdynvc","INFO\t[%s() @ %d]: trans_force_write() finished",__func__,__LINE__); + } + if (tlocked) { + trans->locked = 0; + TC_MUTEX_UNLOCK(trans->lock); + tlocked = 0; + } + TC_MUTEX_UNLOCK(mutex_data); + } + else { + struct stream * qs = (struct stream *)NULL; + DECLARE_SQ(tmp); + make_stream(qs); + init_stream(qs,tlen); + g_memcpy(qs->data,cp,tlen); + tmp->s = qs; + TC_MUTEX_LOCK(&(chan->ilock)); + SQ_ENQ(chan->ihead, tmp); + TC_COND_SIGNAL(cond_data); + { + tc_t tattr; + tc_p pattr = &tattr; + g_memset(pattr,0,sizeof(tc_t)); + TC_CONDATTR_INIT(pattr); + TC_CONDATTR_SETPSHARED(pattr, TC_PROCESS_PRIVATE); + TC_COND_CREATE(cond_data, pattr); + } + if (chan->irem > 0) { + if (chan->irem > tlen) { + MDBGLOG("drdynvc","ERROR\t[%s()]: incoming data is greater than the remaining count",__func__); + chan->irem = 0; + } + else { + chan->irem -= tlen; + } + } + if (chan->irem == 0) { + tc_t tattr; + tc_p pattr = &tattr; + g_memset(pattr,0,sizeof(tc_t)); + TC_CONDATTR_INIT(pattr); + g_data_in_progress[idx] = 0; + chan->ilen = 0; + chan->istatus = 0; + r = trans_get_out_s(trans, MAX_STREAM); + if (r == NULL || r->data == NULL) { + MDBGLOG("drdynvc","ERROR\t[%s() @ %d]: r is NULL or invalid",__func__,__LINE__); + rv = -1; + goto exit; + } + TC_COND_BROADCAST(&(chan->icv)); + TC_COND_CREATE(&(chan->icv), pattr); + } + TC_MUTEX_UNLOCK(&(chan->ilock)); + TC_MUTEX_UNLOCK(mutex_data); + } + } + } + exit:; + return rv; +} + +/*****************************************************************************/ +static int APP_CC drdynvc_process_CLOSE(struct stream * s) { + int rv = 0; + ptrdiff_t idx = -1; + drdynvc_t * chan = (drdynvc_t *)NULL; + char * tp = (char *)(s->p); + DYNVC_CLOSE * cclose = (DYNVC_CLOSE *)NULL; + cclose = RDPEDYC_NEW(DYNVC_CLOSE); + get_DYNVC_CLOSE(cclose, s); + //g_hexdump_file("/tmp/taskq_hex_DYNVC_CLOSE.hexdump",tp,(s->end - tp)); + idx = cclose->ChannelId; + if (idx > -1 && idx < MAX_CHANNEL && idx < g_drdynvc_count && (chan = get_channel(idx)) != NULL) { + ptrdiff_t j = 0; + TC_MUTEX_LOCK(mutex_data); + if (g_drdynvc_arr[idx] != NULL && g_drdynvc_arr[idx]->channel_id == idx) { + drdynvc_t * tmp = g_drdynvc_arr[idx]; + TC_MUTEX_LOCK(&(tmp->ilock)); + g_drdynvc_arr[idx] = (drdynvc_t *)NULL; + TC_MUTEX_UNLOCK(&(tmp->ilock)); + g_free(tmp); + tmp = (drdynvc_t *)NULL; + } + else for (j = 0; j < g_drdynvc_count; j++) { + if (g_drdynvc_arr[j] != NULL && g_drdynvc_arr[j]->channel_id == idx) { + drdynvc_t * tmp = g_drdynvc_arr[j]; + TC_MUTEX_LOCK(&(tmp->ilock)); + g_drdynvc_arr[j] = (drdynvc_t *)NULL; + TC_MUTEX_UNLOCK(&(tmp->ilock)); + g_free(tmp); + tmp = (drdynvc_t *)NULL; + break; + } + } + TC_MUTEX_UNLOCK(mutex_data); + } + return rv; +} + +/*****************************************************************************/ +static inline drdynvc_t * APP_CC get_channel(DWORD arg) { + drdynvc_t * rv = (drdynvc_t *)NULL; + ptrdiff_t i = 0; + if (arg > -1 && arg < MAX_CHANNEL && arg < g_drdynvc_count && g_drdynvc_arr[arg] != NULL && g_drdynvc_arr[arg]->channel_id == arg) { + rv = g_drdynvc_arr[arg]; + } + else if (g_drdynvc_arr != NULL && g_drdynvc_count > 0) { + for (i = 0; i < g_drdynvc_count; i++) { + drdynvc_t * tmp = g_drdynvc_arr[i]; + if (tmp != NULL && tmp->channel_id == arg) { + rv = tmp; + break; + } + } + } + return rv; +} + +/*****************************************************************************/ +static void * APP_CC drdynvc_data_loop(void * arg) { + void * rv = (void *)NULL; + unsigned char done = 0; + TC_MUTEX_LOCK(mutex_close); + done = g_done; + TC_MUTEX_UNLOCK(mutex_close); + while (!done) { + ptrdiff_t i = 0; + TC_MUTEX_LOCK(mutex_data); + TC_COND_WAIT(cond_data, mutex_data); + for (i = 0; i < MAX_CHANNEL && i < g_drdynvc_count; i++) if (g_drdynvc_arr[i] != NULL && g_drdynvc_arr[i]->ihead != NULL) { + drdynvc_t * chan = g_drdynvc_arr[i]; + stream_list_t * item = (stream_list_t *)NULL; + do { + struct stream * s = (struct stream *)NULL; + TC_MUTEX_LOCK(&(chan->ilock)); + SQ_DEQ(chan->ihead, &item); + TC_MUTEX_UNLOCK(&(chan->ilock)); + if (item != NULL) { + s = item->s; + if (s == NULL) { + MDBGLOG("drdynvc","WARNING\t[%s()]: item->s is NULL",__func__); + } + else { + MDBGLOG("drdynvc","INFO\t[%s()]: outputting buffer (item = %p; size = %d; (end - data) = %d)",__func__,s,s->size,(s->end - s->data)); + //g_hexdump_file("/tmp/taskq_hex_buffer.hexdump",s->data,(s->end - s->data)); + } + } + } while (item != NULL); + } + TC_MUTEX_UNLOCK(mutex_data); + TC_MUTEX_LOCK(mutex_close); + done = g_done; + TC_MUTEX_UNLOCK(mutex_close); + } + TC_THREAD_EXIT(NULL); + return rv; +} + +/*****************************************************************************/ +static int APP_CC drdynvc_handle_connection(tbus sck_obj) { + int rv = 0; + tbus in_sck = -1; + int error = 0; + drdynvc_t * channel = (drdynvc_t *)NULL; + tc_t tattr; + tc_t wattr; + tc_p pattr = &tattr; + tc_p rattr = &wattr; + MDBGLOG("drdynvc","INFO\t[%s()]: incoming connection",__func__); + if (sck_obj < 1) { + sck_obj = g_sck; + } + in_sck = g_tcp_accept(sck_obj); + if ((in_sck == -1) && g_tcp_last_error_would_block(g_sck)) { + /* should not get here */ + g_sleep(100); + } + else if (in_sck == -1) { + /* error, should not get here */ + } + else { + /* we've got a connection */ + MDBGLOG("drdynvc", "INFO\t[%s()]: new connection (sck_obj = %d, in_sck = %d)",__func__,sck_obj,in_sck); + g_memset(pattr,0,sizeof(tc_t)); + g_memset(rattr,0,sizeof(tc_t)); + TC_MUTEX_LOCK(mutex_channel_list); + if (g_sck_arr == NULL) { + g_sck_arr = (tbus *)g_malloc(sizeof(tbus), 1); + g_sck_arr[0] = -1; + } + else { + g_sck_arr = (tbus *)g_realloc(g_sck_arr, sizeof(tbus) * (g_sck_count + 1)); + g_sck_arr[g_sck_count] = -1; + } + g_sck_arr[g_sck_count] = in_sck; + g_sck_count++; + if (g_channel_list == NULL) { + g_channel_list = (drdynvc_list_t *)g_malloc(sizeof(drdynvc_list_t), 1); + } + if (g_channel_list->ChannelList == NULL) { + unsigned int i = 0; + g_channel_list->ChannelList = (drdynvc_t **)g_malloc(sizeof(size_t) * MAX_CHANNEL, 1); + } + else { + //g_channel_list->ChannelList = (drdynvc_t **)g_realloc(g_channel_list->ChannelList, sizeof(size_t) * (g_channel_list->ChannelCount + 1)); + g_channel_list->ChannelList = (drdynvc_t **)realloc(g_channel_list->ChannelList, sizeof(size_t) * (g_channel_list->ChannelCount + 1)); + } + channel = (drdynvc_t *)g_malloc(sizeof(drdynvc_t) + 48, 1); + TC_MUTATTR_INIT(rattr); + TC_MUTATTR_SETTYPE(rattr,TC_MUTEX_ERRORCHECK); + TC_MUTATTR_SETPSHARED(rattr,TC_PROCESS_PRIVATE); + TC_CONDATTR_INIT(pattr); + TC_CONDATTR_SETPSHARED(pattr,TC_PROCESS_PRIVATE); + TC_MUTEX_INIT(&(channel->ilock),rattr); + TC_COND_CREATE(&(channel->icv),pattr); + TC_MUTEX_INIT(&(channel->olock),rattr); + TC_COND_CREATE(&(channel->ocv),pattr); + g_channel_list->ChannelList[(g_channel_list->ChannelCount)] = channel; + channel->index = g_channel_list->ChannelCount; + if (g_drdynvc_arr == NULL) { + g_drdynvc_arr = g_channel_list->ChannelList; + } + g_channel_list->ChannelCount++; + channel->channel_id = reserve_channel_id() + 1; + channel->acknowledged = 0x00; + channel->ccon = trans_create(g_drdynvc_socket_type, MAX_STREAM, MAX_STREAM); + if (channel->ccon == NULL) { + TC_MUTEX_UNLOCK(mutex_channel_list); + rv = -1; + } + else { + TC_MUTEX_LOCK(channel->ccon->lock); + channel->ccon->locked = 1; + channel->ccon->sck = -1; + trans_attach(channel->ccon, in_sck); + g_tcp_set_non_blocking(in_sck); + channel->ccon->sck = in_sck; + channel->ccon->trans_data_in = &app_data_in; + channel->ccon->callback_data = channel; + channel->ccon->header_size = 24; + channel->ccon->ready = 1; + channel->ccon->running = 1; + channel->initialized = 1; + channel->ccon->locked = 0; + TC_MUTEX_UNLOCK(channel->ccon->lock); + TC_MUTEX_UNLOCK(mutex_channel_list); + } + } + end:; + MDBGLOG("drdynvc","INFO\t[%s()]: done.",__func__); + return rv; +} + +/*****************************************************************************/ +static ptrdiff_t APP_CC reserve_channel_id() { + ptrdiff_t rv = -1; + ptrdiff_t i = 0; + TC_MUTEX_LOCK(mutex_id); + for (i = 0; i < MAX_CHANNEL; i++) if (g_channel_ids[i] < 1) { + rv = i; + g_channel_ids[i] = 1; + } + TC_MUTEX_UNLOCK(mutex_id); + return rv; +} + +/*****************************************************************************/ +static ptrdiff_t APP_CC release_channel_id(ptrdiff_t id) { + ptrdiff_t rv = 0; + if (id > -1 && id < MAX_CHANNEL) { + TC_MUTEX_LOCK(mutex_id); + g_channel_ids[id] = 0; + TC_MUTEX_UNLOCK(mutex_id); + } + return rv; +} + +/*****************************************************************************/ +/****** Operation IDs ******/ +/*****************************************************************************/ + +/*****************************************************************************/ +static ptrdiff_t APP_CC get_opid(void * idev) { + ptrdiff_t rv = 0; + drdynvc_t * chan = (drdynvc_t *)idev; + if (chan == NULL) { + rv = -1; + } + else { + if (chan->top_opid == 0) { + chan->top_opid++; + } + rv = chan->top_opid++; + register_opid(chan, rv); + } + return rv; +} + +/*****************************************************************************/ +static ptrdiff_t APP_CC register_opid(void * ichan, ptrdiff_t opid) { + ptrdiff_t rv = -1; + ptrdiff_t idx = 0; + ptrdiff_t tmp = -1; + drdynvc_t * chan = (drdynvc_t *)ichan; + if (chan == NULL) { + rv = -1; + } + else { + for (idx = 0; idx < MAX_PENDING; idx++) { + if ((tmp < 0) && (chan->pending_opids[idx] == 0)) { + tmp = idx; + rv = idx; + chan->pending_opids[idx] = opid; + } + else if (chan->pending_opids[idx] == opid) { + /* ERROR: the opid is already registered */ + rv = -1; + if (tmp > -1) { + chan->pending_opids[tmp] = 0; + } + MDBGLOG("redir","ERROR\t[%s()]: \"%d\" is already registered at position %d",__func__,opid,idx); + break; + } + } + } + if (rv > -1) { + if (chan->callbacks != NULL) { + tc_t tattr; + tc_t uattr; + tc_p mattr = &tattr; + tc_p cattr = &uattr; + TC_MUTATTR_INIT(mattr); + TC_MUTATTR_SETTYPE(mattr,TC_MUTEX_ERRORCHECK); + TC_MUTATTR_SETPSHARED(mattr,TC_PROCESS_SHARED); + TC_CONDATTR_INIT(cattr); + TC_CONDATTR_SETPSHARED(cattr,TC_PROCESS_SHARED); + TC_MUTEX_INIT(&(chan->callbacks[rv].mutex),mattr); + TC_COND_CREATE(&(chan->callbacks[rv].cv),cattr); + chan->callbacks[rv].opid = opid; + chan->callbacks[rv].type = 0; + chan->callbacks[rv].channel_id = chan->channel_id; + chan->callbacks[rv].channel = chan; + chan->callbacks[rv].fd = chan->socket; + chan->callbacks[rv].trans = chan->ccon; + } + rv = 0; + } + return rv; +} + +/*****************************************************************************/ +static ptrdiff_t APP_CC strike_opid(void * idev, ptrdiff_t opid) { + ptrdiff_t rv = 0; + drdynvc_t * chan = (drdynvc_t *)idev; + rv = opid_is_registered(chan, opid); + if (rv > 0) { + chan->pending_opids[rv] = 0; + if (chan->callbacks != NULL) { + if (chan->callbacks[rv].data != NULL && chan->callbacks[rv].length > 0) { + g_memset(chan->callbacks[rv].data,0,chan->callbacks[rv].length); + //g_free(chan->callbacks[rv].data); + chan->callbacks[rv].data = (BYTE *)NULL; + } + g_memset(&(chan->callbacks[rv]),0,sizeof(callback)); + //g_free(chan->callbacks[rv]); + //chan->callbacks[rv] = (callback *)NULL; + } + } + return rv; +} + +/*****************************************************************************/ +static int APP_CC opid_is_registered(void * idev, ptrdiff_t opid) { + int rv = 0; + ptrdiff_t idx = 0; + drdynvc_t * chan = (drdynvc_t *)idev; + if (chan == NULL) { + rv = -1; + } + else { + for (idx = 0; idx < MAX_PENDING; idx++) { + if (chan->pending_opids[idx] == opid) { + rv = idx; + break; + } + } + } + return rv; +} + +static inline const char * nterr_msg(uint32_t err) { + char * rv = (char *)NULL; + uint32_t i = 0x00000000; + const nterr_msg_t nterr[] = NTERRMSG_ARRAY; + + for (i = 0; i < (sizeof(nterr) / sizeof(nterr_msg_t)); i++) { + if (nterr[i].ntstatus == err) { + rv = (char *)(nterr[i].msg); + break; + } + } + + return (const char *)rv; +} diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/drdynvc.h posixrdp/posixxrdp.orig/sesman/chansrv/drdynvc.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/drdynvc.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/drdynvc.h 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,23 @@ + +#if !defined(DRDYNVC_H) +#define DRDYNVC_H + +#include +#include "defines.h" +#include "ntstatus.h" +#include "arch.h" +#include "parse.h" +#include "stream_list.h" + +int APP_CC +drdynvc_init(void); +int APP_CC +drdynvc_deinit(void); +int APP_CC +drdynvc_data_in(struct stream *, int, int, int, int); +int APP_CC +drdynvc_get_wait_objs(tbus* objs, int* count, int* timeout); +int APP_CC +drdynvc_check_wait_objs(void); + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/fuse_i.h posixrdp/posixxrdp.orig/sesman/chansrv/fuse_i.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/fuse_i.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/fuse_i.h 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,25 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2006 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPL. + See the file COPYING.LIB +*/ + +#include "fuse.h" + +struct fuse_session; +struct fuse_chan; + +struct fuse_cmd { + char *buf; + size_t buflen; + struct fuse_chan *ch; +}; + +struct fuse_session *fuse_get_session(struct fuse *f); + +struct fuse *fuse_new_common(int fd, struct fuse_args *args, + const struct fuse_operations *op, + size_t op_size, int compat); + diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/global.h posixrdp/posixxrdp.orig/sesman/chansrv/global.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/global.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/global.h 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,30 @@ +/* GLOBAL.H - RSAREF types and constants + */ + +/* PROTOTYPES should be set to one if and only if the compiler supports + function argument prototyping. +The following makes PROTOTYPES default to 0 if it has not already + been defined with C compiler flags. + */ +#ifndef PROTOTYPES +#define PROTOTYPES 0 +#endif + +/* POINTER defines a generic pointer type */ +typedef unsigned char *POINTER; + +/* UINT2 defines a two byte word */ +typedef unsigned short int UINT2; + +/* UINT4 defines a four byte word */ +typedef unsigned int UINT4; + +/* PROTO_LIST is defined depending on how PROTOTYPES is defined above. +If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it + returns an empty list. + */ +#if PROTOTYPES +#define PROTO_LIST(list) list +#else +#define PROTO_LIST(list) () +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/Makefile.am posixrdp/posixxrdp.orig/sesman/chansrv/Makefile.am --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/Makefile.am 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/Makefile.am 2010-11-08 09:56:45.000000000 +0100 @@ -1,23 +1,59 @@ AM_CFLAGS = \ + -pthread \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ -DXRDP_SBIN_PATH=\"${sbindir}\" \ -DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \ - -DXRDP_PID_PATH=\"${localstatedir}/run\" + -DXRDP_PID_PATH=\"${localstatedir}/run\" \ + -D_FILE_OFFSET_BITS=64 \ + -D_REENTRANT \ + -D_GNU_SOURCE \ + -D_XOPEN_SOURCE_EXTENDED \ + -DXRDP_ENABLE_IMA_ADPCM + +LDFLAGS = \ + -lpthread INCLUDES = \ - -I$(top_srcdir)/common + -I$(top_srcdir)/common \ + -I/usr/lib/glib/include \ + -I/usr/include/glib-1.2 \ + -I/usr/lib/glib-1.2/include sbin_PROGRAMS = \ xrdp-chansrv xrdp_chansrv_SOURCES = \ + global.h \ chansrv.c \ + chansrv.h \ sound.c \ + sound.h \ clipboard.c \ - devredir.c + clipboard.h \ + devredir.c \ + devredir.h \ + params.h \ + rdpdr_defs.h \ + rdpfs.c \ + fuse_i.h \ + rdpport.c \ + rdpport_defs.h \ + rdpprint.c \ + rdpsc.c \ + md5c.c \ + md5.h \ + drdynvc.c \ + drdynvc.h xrdp_chansrv_LDADD = \ -L/usr/X11R6/lib \ - $(top_srcdir)/common/libcommon.la \ - -lX11 -lXfixes + $(top_builddir)/common/libcommon.la + +xrdp_chansrv_LDFLAGS = \ + -lX11 \ + -lXfixes \ + -lxcb \ + -lfuse \ + -lm \ + -lpulse diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/md5c.c posixrdp/posixxrdp.orig/sesman/chansrv/md5c.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/md5c.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/md5c.c 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,312 @@ +/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + +#include +#include +#include "global.h" +#include "md5.h" + +/* Constants for MD5Transform routine. + */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +static void APP_CC MD5Transform (UINT4 [4], unsigned char [64]); +static void APP_CC Encode (unsigned char *, UINT4 *, size_t); +static void APP_CC Decode (UINT4 *, unsigned char *, size_t); +static inline void APP_CC MD5_memcpy (POINTER, POINTER, size_t); +static inline void APP_CC MD5_memset (POINTER, int, size_t); + +static unsigned char PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* F, G, H and I are basic MD5 functions. + */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. + */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +Rotation is separate from addition to prevent recomputation. + */ +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +/* MD5 initialization. Begins an MD5 operation, writing a new context. + */ +void APP_CC MD5Init (MD5_CTX * context) { + context->count[0] = context->count[1] = 0; + /* Load magic initialization constants. +*/ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* MD5 block update operation. Continues an MD5 message-digest + operation, processing another message block, and updating the + context. + */ +void APP_CC MD5Update (MD5_CTX * context, unsigned char * input, size_t inputLen) { + size_t index = 0; + ptrdiff_t dindex = 0; + ptrdiff_t i = 0; + ptrdiff_t partLen = 0; + + /* Compute number of bytes mod 64 */ + index = (size_t)((context->count[0] >> 3) & 0x3F); + dindex = index; + + /* Update number of bits */ + if ((context->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3)) { + (context->count[1])++; + context->count[1] += ((UINT4)inputLen >> 29); + } + + partLen = 64 - index; + + /* Transform as many times as possible. +*/ + if (inputLen >= partLen) { + MD5_memcpy((POINTER)&context->buffer[dindex], (POINTER)input, partLen); + MD5Transform (context->state, context->buffer); + for (i = partLen; (i + 63) < inputLen; i += 64) { + MD5Transform (context->state, &(input[i])); + } + dindex = 0; + index = 0; + } + else { + i = 0; + } + + /* Buffer remaining input */ + MD5_memcpy((POINTER)(&(context->buffer[dindex])), (POINTER)(&(input[i])), (inputLen - i)); +} + +/* MD5 finalization. Ends an MD5 message-digest operation, writing the + the message digest and zeroizing the context. + */ +void APP_CC MD5Final (unsigned char digest[16], MD5_CTX * context) { + unsigned char bits[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + size_t index = 0; + size_t padLen = 0; + + /* Save number of bits */ + Encode (bits, context->count, 8); + + /* Pad out to 56 mod 64. */ + index = (size_t)((context->count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + MD5Update (context, PADDING, padLen); + + /* Append length (before padding) */ + MD5Update (context, bits, 8); + /* Store state in digest */ + Encode (digest, context->state, 16); + + /* Zeroize sensitive information. */ + MD5_memset ((POINTER)context, 0, sizeof (*context)); +} + +/* MD5 basic transformation. Transforms state based on block. + */ +static void APP_CC MD5Transform (UINT4 state[4], unsigned char block[64]) { + UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + Decode (x, block, 64); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. +*/ + MD5_memset ((POINTER)x, 0, sizeof (x)); +} + +/* Encodes input (UINT4) into output (unsigned char). Assumes len is + a multiple of 4. + */ +static void APP_CC Encode (unsigned char * output, UINT4 * input, size_t len) { + ptrdiff_t i = 0; + ptrdiff_t j = 0; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (unsigned char)(input[i] & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); + } +} + +/* Decodes input (unsigned char) into output (UINT4). Assumes len is + a multiple of 4. + */ +static void APP_CC Decode (UINT4 * output, unsigned char * input, size_t len) { + ptrdiff_t i = 0; + ptrdiff_t j = 0; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[i] = ((UINT4)(input[j])) | (((UINT4)(input[(j+1)])) << 8) | (((UINT4)(input[(j+2)])) << 16) | (((UINT4)(input[(j+3)])) << 24); + } +} + +/* Note: Replace "for loop" with standard memcpy if possible. + */ + +static inline void APP_CC MD5_memcpy (POINTER output, POINTER input, size_t len) { + ptrdiff_t i = 0; + + for (i = 0; i < len; i++) { + output[i] = input[i]; + } +} + +/* Note: Replace "for loop" with standard memset if possible. + */ +static inline void APP_CC MD5_memset (POINTER output, int value, size_t len) { + ptrdiff_t i = 0; + if (1) { + memset(output,value,len); + } + else for (i = 0; i < len; i++) { + ((char *)output)[i] = (char)value; + } +} diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/md5.h posixrdp/posixxrdp.orig/sesman/chansrv/md5.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/md5.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/md5.h 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,54 @@ +/* MD5.H - header file for MD5C.C + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + +#include +#include + +#if !defined(UINT4) +#define UINT4 uint32_t +#endif + +#if !defined(APP_CC) +#define APP_CC +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* MD5 context. */ +typedef struct _MD5_CTX { + UINT4 state[4]; /* state (ABCD) */ + UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +} MD5_CTX; + +void APP_CC MD5Init (MD5_CTX *); +void APP_CC MD5Update (MD5_CTX *, unsigned char *, size_t); +void APP_CC MD5Final (unsigned char [16], MD5_CTX *); + +#ifdef __cplusplus +} +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/params.h posixrdp/posixxrdp.orig/sesman/chansrv/params.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/params.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/params.h 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,29 @@ +// There are a couple of symbols that need to be #defined before +// #including all the headers. + +#ifndef _PARAMS_H_ +#define _PARAMS_H_ + +// The FUSE API has been changed a number of times. So, our code +// needs to define the version of the API that we assume. As of this +// writing, the most current API version is 26 +#define FUSE_USE_VERSION 26 + +// need this to get pwrite(). I have to use setvbuf() instead of +// setlinebuf() later in consequence. +#define _XOPEN_SOURCE 500 + +// maintain bbfs state in here +#include +#include + +#ifndef __RDPFS_STATE__ +#define __RDPFS_STATE__ +struct rdpfs_state { + FILE *logfile; + char *rootdir; +}; +#define RDPFS_DATA ((struct rdpfs_state *) fuse_get_context()->private_data) +#endif + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/rdpfs.c posixrdp/posixxrdp.orig/sesman/chansrv/rdpfs.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/rdpfs.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/rdpfs.c 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,6437 @@ +/* + * + * RDP File System for device redirection + * + */ + +#ifdef FUSE_USE_VERSION +#undef FUSE_USE_VERSION +#endif + +#define FUSE_USE_VERSION 26 + +#include "params.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ + +#include "log.h" +#include "arch.h" +#include "parse.h" +#include "defines.h" +#include "rdpdr.h" +#include "rdpdr_methods.h" +#include "fuse_i.h" +#include "trans.h" +#include "devredir_defs.h" +#include "global.h" +#include "md5.h" +#include "thread_calls.h" +#include "thread_macros.h" +#include "crc32.h" +#include "dbg.h" + + +//#if defined(MDBGLOG) +//#undef MDBGLOG +//#define MDBGLOG(...) ; +//#endif + + +#ifndef MAX_REQID +#define MAX_REQID 25 +#endif + + +extern int g_fs_count; +extern char * APP_CC ntstatus_string(uint32_t); + + +static rdpfs * g_rdpfs = (rdpfs *)NULL; +static rdpfs ** g_fs_arr = (rdpfs **)NULL; +static tc_p mutex_fs_arr = (tc_p)NULL; + +static tc_p mutex_pcon_fs = (tc_p)NULL; +static tc_p mutex_fs = (tc_p)NULL; +static tc_p mutex_parent_fs = (tc_p)NULL; +static tc_p mutex_fuse = (tc_p)NULL; +static tc_p mutex_fsop = (tc_p)NULL; +static tc_p mutex_reqid_fs = (tc_p)NULL; +static tc_p mutex_getattr = (tc_p)NULL; +static tc_p cv_readdir = (tc_p)NULL; + +static struct _rdpstat { + unsigned char set; + char path[255]; + struct stat st; +} g_fattr_cache[MAX_REQID] = { }; + +static int APP_CC rdpfs_open(const char *, struct fuse_file_info *); +static int APP_CC rdpfs_open_args(const char *, struct fuse_file_info *, uint32_t, uint32_t, uint32_t, uint32_t); +static int APP_CC rdpfs_getattr(const char *, struct stat *); +static int APP_CC rdpfs_fgetattr(const char *, struct stat *, struct fuse_file_info *); +static int APP_CC rdpfs_release(const char *, struct fuse_file_info *); +static int APP_CC rdpfs_read_chunk(const char *, char *, size_t, off_t, struct fuse_file_info *); +static int APP_CC rdpfs_create(const char *, mode_t, struct fuse_file_info *); +static int APP_CC rdpfs_create_args(const char *, mode_t, struct fuse_file_info *, uint32_t, uint32_t, uint32_t, uint32_t); +static int APP_CC rdpfs_mkdir(const char *, mode_t); +static int APP_CC rdpfs_write_chunk(const char *, const char *, size_t, off_t, struct fuse_file_info *); +static int APP_CC rdpfs_releasedir(const char *, struct fuse_file_info *); +static int APP_CC rdpfs_write(const char *, const char *, size_t, off_t, struct fuse_file_info *); +static int APP_CC rdpfs_ftruncate(const char *, off_t, struct fuse_file_info *); +static int APP_CC rdpfs_fsctl(const char *, struct fuse_file_info *, DWORD, int, void *); + +static int APP_CC get_reqid_fs(int *); +static int APP_CC free_reqid_fs(int); +static int APP_CC init_reqids_fs(rdpfs *); +static int APP_CC get_mutex_fs(int, tc_p *, rdpfs *); +static int APP_CC get_cv_fs(int, tc_p *, rdpfs *); +static int APP_CC get_cbdata_fs(int reqid, callback **); +static int APP_CC ntstatus_to_errcode(DWORD); +static APP_CC int rdpfs_parse_path(const char *, char **, char **); + +static int APP_CC construct_MINSHALL_FRENCH_SYMLINK(MINSHALL_FRENCH_SYMLINK *); +static char * APP_CC get_MINSHALL_FRENCH_SYMLINK(MINSHALL_FRENCH_SYMLINK *); +static int APP_CC set_MINSHALL_FRENCH_SYMLINK(MINSHALL_FRENCH_SYMLINK *, const char *); +static int APP_CC input_MINSHALL_FRENCH_SYMLINK(MINSHALL_FRENCH_SYMLINK *, struct stream *); +static int APP_CC send_MINSHALL_FRENCH_SYMLINK(MINSHALL_FRENCH_SYMLINK *, struct stream *); + +static int APP_CC send_INTERIX_DEV_FILE(INTERIX_DEV_FILE *, struct stream *); +static int APP_CC set_INTERIX_DEV_FILE(INTERIX_DEV_FILE *, char, int64_t, int64_t); +static int APP_CC construct_INTERIX_DEV_FILE(INTERIX_DEV_FILE *); + +static size_t APP_CC parent_data_in(struct trans *); + +static struct fuse * rdpfs_setup_common(int argc, char *argv[], + const struct fuse_operations *, + size_t, + char **, + int *, + int *, + struct fuse_chan **, + int, + struct rdpfs_state *); + +static const struct fuse_opt fuse_helper_opts[] = { + FUSE_HELPER_OPT("-d", foreground), + FUSE_HELPER_OPT("debug", foreground), + FUSE_HELPER_OPT("-f", foreground), + FUSE_HELPER_OPT("-s", singlethread), + FUSE_HELPER_OPT("fsname=", fsname), + + FUSE_OPT_KEY("-h", KEY_HELP), + FUSE_OPT_KEY("--help", KEY_HELP), + FUSE_OPT_KEY("-ho", KEY_HELP_NOHEADER), + FUSE_OPT_KEY("-V", KEY_VERSION), + FUSE_OPT_KEY("--version", KEY_VERSION), + FUSE_OPT_KEY("-d", KEY_KEEP), + FUSE_OPT_KEY("debug", KEY_KEEP), + FUSE_OPT_KEY("fsname=", KEY_KEEP), + FUSE_OPT_END +}; + +static int rdpfs_parse_cmdline(struct fuse_args *args, char **mountpoint, + int *multithreaded, int *foreground); + +static int rdpfs_readlink(const char *, char *, size_t); + +/* Report errors to logfile and give -errno to caller */ +static int rdpfs_error(char * str) { + int ret = -errno; + + MDBGLOG("rdpfs"," %s: %s\n", str, strerror(errno)); + + return ret; +} + +static void rdpfs_fullpath(char fpath[PATH_MAX], const char * path) { + if (fpath != NULL && path != NULL) { + g_snprintf(fpath,(PATH_MAX - 1),"%s",path); + } +} + +static int rdpfs_is_symlink(const char * path) { + int retstat = 0; + char * fpath = (char *)NULL; + ptrdiff_t rlen = 0; + char lpath[PATH_MAX] = ""; + + g_memset(lpath,0,sizeof(char)*PATH_MAX); + + fpath = (char *)g_strdup(path); + rlen = rdpfs_readlink(fpath,lpath,PATH_MAX); + if (rlen > -1 && g_strlen(lpath) > 0) { + retstat = 1; + } + else { + retstat = 0; + } + + if (retstat > 0) { + MDBGLOG("rdpfs","* \"%s\" IS a symlink",path); + } + else { + MDBGLOG("rdpfs","* \"%s\" is NOT a symlink",path); + } + + if (fpath != NULL && g_strlen(fpath) > 0) { + g_free(fpath); + } + + return retstat; +} + +static int rdpfs_is_blk_file(const char * path) { + int retstat = 0; + char * fpath = (char *)NULL; + size_t tsize = 24; + off_t toffset = 0; + ptrdiff_t rlen = 0; + char lpath[PATH_MAX]; + struct fuse_file_info lfi; + struct fuse_file_info * fi = &lfi; + INTERIX_DEV_FILE ldf; + INTERIX_DEV_FILE * df = &ldf; + LOCAL_STREAM(s); + + g_memset(lpath,0,sizeof(char)*PATH_MAX); + g_memset(&ldf,0,sizeof(INTERIX_DEV_FILE)); + g_memset(&lfi,0,sizeof(struct fuse_file_info)); + fi->flags |= O_RDONLY; + + fpath = (char *)g_strdup(path); + rlen = rdpfs_open(fpath, fi); + if (rlen < 0) { + retstat = rlen; + goto rel_tag; + } + rdpfs_read_chunk(fpath,(char *)(s->data),tsize,toffset,fi); + s->p += tsize; + s_mark_end(s); + s->p = s->data; + in_uint8a(s, df->magic, 8); + in_uint64_le(s, df->major); + in_uint64_le(s, df->minor); + + if (df != NULL && df->magic != NULL && df->magic[0] == 'I' && df->magic[1] == 'n' && df->magic[2] == 't' && df->magic[3] == 'x' && df->magic[4] == 'B' && df->magic[5] == 'L' && df->magic[6] == 'K' && df->magic[7] == '\0') { + int tmaj = df->major; + int tmin = df->minor; + retstat = makedev(tmaj,tmin); + } + else { + retstat = 0; + } + + if (retstat > 0) { + MDBGLOG("rdpfs","* \"%s\" IS a block device",path); + } + else { + MDBGLOG("rdpfs","* \"%s\" is NOT a block device",path); + } + + rel_tag: + if (fpath != NULL && g_strlen(fpath) > 0 && fi != NULL && fi->fh > 0) { + rdpfs_release(fpath,fi); + } + + if (fpath != NULL && g_strlen(fpath) > 0) { + g_free(fpath); + } + + return retstat; +} + +static int rdpfs_is_chr_file(const char * path) { + int retstat = 0; + char * fpath = (char *)NULL; + size_t tsize = 24; + off_t toffset = 0; + ptrdiff_t rlen = 0; + char lpath[PATH_MAX] = ""; + struct fuse_file_info lfi; + struct fuse_file_info * fi = &lfi; + INTERIX_DEV_FILE ldf; + INTERIX_DEV_FILE * df = &ldf; + LOCAL_STREAM(s); + + g_memset(lpath,0,sizeof(char)*PATH_MAX); + g_memset(&ldf,0,sizeof(INTERIX_DEV_FILE)); + g_memset(&lfi,0,sizeof(struct fuse_file_info)); + fi->flags |= O_RDONLY; + + fpath = (char *)g_strdup(path); + rlen = rdpfs_open(fpath, fi); + if (rlen < 0) { + retstat = rlen; + goto rel_tag; + } + rlen = rdpfs_read_chunk(fpath,(char *)(s->data),tsize,toffset,fi); + if (rlen != 24) { + retstat = -1; + goto rel_tag; + } + s->p += tsize; + s_mark_end(s); + s->p = s->data; + in_uint8a(s, df->magic, 8); + in_uint64_le(s, df->major); + in_uint64_le(s, df->minor); + + if (df != NULL && df->magic != NULL && df->magic[0] == 'I' && df->magic[1] == 'n' && df->magic[2] == 't' && df->magic[3] == 'x' && df->magic[4] == 'C' && df->magic[5] == 'H' && df->magic[6] == 'R' && df->magic[7] == '\0') { + int tmaj = df->major; + int tmin = df->minor; + retstat = makedev(tmaj,tmin); + } + else { + retstat = 0; + } + + if (retstat > 0) { + MDBGLOG("rdpfs","* \"%s\" IS a character device",path); + } + else { + MDBGLOG("rdpfs","* \"%s\" is NOT a character device",path); + } + + rel_tag:; + if (fpath != NULL && g_strlen(fpath) > 0 && fi != NULL && fi->fh > 0) { + rdpfs_release(fpath,fi); + } + + if (fpath != NULL && g_strlen(fpath) > 0) { + g_free(fpath); + } + + return retstat; +} + +/** Get file attributes. + * + * Similar to stat(). The 'st_dev' and 'st_blksize' fields are + * ignored. The 'st_ino' field is ignored except if the 'use_ino' + * mount option is given. + */ +int rdpfs_getattr(const char * ipath, struct stat * statbuf) { + RDPFS_DECS; + int retstat = 0; + //tbus fd = -1; + DIR * dp = (DIR *)NULL; + char fpath[PATH_MAX] = ""; + struct stream * s = NULL; + char buf[512] = ""; + struct stat st; + ptrdiff_t ldx = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + ptrdiff_t size = 0x00000000; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + struct fuse_file_info * lfi = NULL; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + filelist_entry * finfo = NULL; + char * path = (char *)NULL; + char * tstream = (char *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + uint32_t crc32 = 0; + unsigned char cached = 0; + + MDBGLOG("rdpfs","\nINFO\t[%s()]: called (ipath=\"%s\", statbuf=0x%8.8x)\n",__func__,ipath,statbuf); + + g_memset(&st,0,sizeof(struct stat)); + g_memset(fpath,0,sizeof(fpath)); + g_memset(buf,0,sizeof(buf)); + + rdpfs_parse_path(ipath, &path, &tstream); + + /* + * Check whether the target path is already in the cache: + */ + if (g_strlen(path) > 0) for (ldx = 0; ldx < MAX_REQID; ldx++) { + if (g_fattr_cache[ldx].set > 0 && !g_strncmp(g_fattr_cache[ldx].path,path,255)) { + cached = 1; + goto bypass; + } + } + ldx = 0; + + lfi = (struct fuse_file_info *)g_malloc(sizeof(struct fuse_file_info), 1); + rdpfs_open(path, lfi); + dp = (DIR *)(uintptr_t)(lfi->fh); + fhandle = (int)(uintptr_t)dp; + + /* Odd bug: it is necessary to close the just-opened file, + * and then re-open it, in order to prevent a wierd off-by-one + * error in directory listings. This probably has something to + * do with the need to flush the filesystem cache or something + * like that... + */ + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *)&lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + rdpfs_opcode = RDPFS_GETATTR; + rdpfs_fullpath(fpath, path); + size = g_strlen(fpath) + 1; + uniqid = reqid; + + cbdata = &(g_reqids[reqid]); + cbdata->userdata = (BYTE *)g_malloc(sizeof(filelist_entry), 1); + cbdata->uniqid = uniqid; + cbdata->FileId = fhandle; + + if (size > 0 && fpath != NULL) { + crc32 = Crc32_ComputeBuf(0, fpath, size); + } + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, size); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + if (size > 0) { + out_uint8a(s, fpath, size); + } + s_mark_end(s); + size = s->end - s->data; + + MDBGLOG("rdpfs"," ** rdpfs_getattr(): sending [g_fd = %d; pcon->sck = %d; FileId = %d; uniqid = %d]", g_fd, pcon->sck, cbdata->FileId, cbdata->uniqid); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + MDBGLOG("rdpfs","sent."); + + MDBGLOG("rdpfs","entering g_obj_wait loop:"); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_WAIT(lcv, lmutex); + MDBGLOG("rdpfs","g_obj_wait loop: exited."); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = (char *)NULL; + nterr = ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("rdpfs","ERROR\t[%s()]: \"%s\" (retstat = %d; cbdata->IoStatus.Value = 0x%8.8x)",__func__,nterr,retstat,cbdata->IoStatus.Value); + //g_free(nterr); + goto end; + } + + finfo = (filelist_entry *)(cbdata->userdata); + g_memset(statbuf,0,sizeof(struct stat)); + statbuf->st_dev = 0x00000801; + statbuf->st_nlink = finfo->NumberOfLinks; + statbuf->st_ctime = FileTimeToUnix(finfo->CreationTime); + statbuf->st_mtime = FileTimeToUnix(finfo->LastWriteTime); + statbuf->st_atime = FileTimeToUnix(finfo->LastAccessTime); + statbuf->st_size = finfo->EndOfFile; + statbuf->st_blocks = finfo->AllocationSize; + statbuf->st_uid = 0; + statbuf->st_gid = 0; + if ((finfo->FileAttributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY) { + statbuf->st_mode = 0644; + } + else { + statbuf->st_mode = 0755; + } + if ((finfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY || finfo->Directory > 0) { + /* + * if the above test is true, then this is a directory: + */ + statbuf->st_mode |= S_IFDIR; + } + else if ((finfo->FileAttributes & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM && rdpfs_is_blk_file(fpath) > 0) { + /* + * if the above test is true, then this is an Interix-type block device file: + */ + statbuf->st_mode |= S_IFBLK; + statbuf->st_rdev |= rdpfs_is_blk_file(fpath); + statbuf->st_size = 0; + statbuf->st_blocks = 0; + } + else if ((finfo->FileAttributes & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM && rdpfs_is_chr_file(fpath) > 0) { + /* + * if the above test is true, then this is an Interix-type character device file: + */ + statbuf->st_mode |= S_IFCHR; + statbuf->st_rdev |= rdpfs_is_chr_file(fpath); + statbuf->st_size = 0; + statbuf->st_blocks = 0; + } + else if ((finfo->FileAttributes & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM && finfo->EndOfFile > 5 && finfo->EndOfFile < 2048 && rdpfs_is_symlink(fpath) > 0) { + /* + * if the above test is true, then this is a "Minshall-French"-type symlink: + */ + statbuf->st_mode |= S_IFLNK; + } + else if ((finfo->FileAttributes & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM && finfo->EndOfFile == 0) { + /* + * if the above test is true, then this is an Interix-style FIFO (named pipe): + */ + statbuf->st_mode |= S_IFIFO; + statbuf->st_size = 0; + statbuf->st_blocks = 0; + } + else if ((finfo->FileAttributes & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM && finfo->EndOfFile == 1) { + /* + * if the above test is true, then this is an Interix-style socket: + */ + statbuf->st_mode |= S_IFSOCK; + statbuf->st_size = 0; + statbuf->st_blocks = 0; + } + else { + statbuf->st_mode |= S_IFREG; + } + + MDBGLOG("rdpfs","\n\n ****** path = \"%s\"; fhandle = %d; finfo->Directory = %d; finfo->FileAttributes = 0x%8.8x\n",path,fhandle,finfo->Directory,finfo->FileAttributes); + + bypass:; + + if (cached) { + MDBGLOG("rdpfs","\n*** cached! path = \"%s\"",path); + g_memcpy(statbuf, &(g_fattr_cache[ldx].st), sizeof(struct stat)); + } + else for (ldx = 0; ldx < MAX_REQID; ldx++) if (!(g_fattr_cache[ldx].set)) { + g_memcpy(&(g_fattr_cache[ldx].st), statbuf, sizeof(struct stat)); + g_fattr_cache[ldx].set = 1; + } + + end:; + + if (cbdata->userdata != NULL) { + g_free(cbdata->userdata); + } + if (lfi != NULL && lfi->fh > 0) { + rdpfs_release(path, lfi); + } + if (lfi != NULL) { + g_free(lfi); + } + g_memset(cbdata,0,sizeof(callback)); + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + return retstat; +} + +/** Read the target of a symbolic link + * + * The buffer should be filled with a null terminated string. The + * buffer size argument includes the space for the terminating + * null character. If the linkname is too long to fit in the + * buffer, it should be truncated. The return value should be 0 + * for success. + */ +// the description given above doesn't correspond to the readlink(2) +// man page -- according to that, if the link is too long for the +// buffer, it ends up without the null termination +static int rdpfs_readlink(const char * ipath, char * ilink, size_t size) { + RDPFS_DECS; + int retstat = 0; + ptrdiff_t tsize = 0; + size_t fsize = 0; + off_t foffset = 0; + struct stream ls; + struct stream * qs = &ls; + BYTE buf[MAX_STREAM]; + char * path = (char *)NULL; + char * link = (char *)NULL; + char * tlink = (char *)NULL; + struct stat lsb; + struct stat * sb = &lsb; + struct fuse_file_info lfi; + struct fuse_file_info * fi = &lfi; + MINSHALL_FRENCH_SYMLINK mfsl; + MINSHALL_FRENCH_SYMLINK * sl = &mfsl; + char fpath[PATH_MAX]; + ptrdiff_t tret = 0; + + g_memset(fpath,0,sizeof(char)*PATH_MAX); + + if (ipath != NULL && ipath[0] != '\0') { + path = (char *)g_strdup(ipath); + link = (char *)ilink; + } + else { + retstat = -1; + goto end_tag; + } + + MDBGLOG("rdpfs","rdpfs_readlink(path=\"%s\", link=\"%s\", size=%d)\n", path, link, size); + + g_memset(fi,0,sizeof(struct fuse_file_info)); + g_memset(sb,0,sizeof(struct stat)); + g_memset(qs,0,sizeof(struct stream)); + g_memset(buf,0,sizeof(BYTE) * MAX_STREAM); + + qs->data = (char *)buf; + qs->size = fsize; + qs->p = qs->data; + + construct_MINSHALL_FRENCH_SYMLINK(sl); + fi->flags |= O_RDONLY; + rdpfs_open(path,fi); + if (fi == NULL || fi->fh < 1) { + retstat = -1; + goto end_tag; + } + rdpfs_fullpath(fpath,path); + fsize = 4096; + qs->end = qs->data + fsize; + tret = rdpfs_read_chunk(fpath,(char *)buf,fsize,foffset,fi); + if (tret < 0) { + retstat = tret; + goto end_tag; + } + input_MINSHALL_FRENCH_SYMLINK(sl, qs); + tlink = get_MINSHALL_FRENCH_SYMLINK(sl); + tsize = g_strlen(tlink); + if (tsize < 1) { + retstat = -1; + } + else { + g_strncpy(link,tlink,MIN(tsize,size)); + } + if (tlink != NULL && tsize > 0) { + g_free(tlink); + tlink = (char *)NULL; + } + + if (fi != NULL && fi->fh > 0) { + rdpfs_release(path,fi); + } + + end_tag: + if (path != NULL && g_strlen(path) > 0) { + path = NULL; + } + return retstat; +} + +/** Create a file node + * + * There is no create() operation; instead, mknod() will be called + * for creation of any non-directory, non-symlink nodes. + */ +// shouldn't that comment be "if" there is no.... ? +int rdpfs_mknod(const char * path, mode_t mode, dev_t dev) { + RDPFS_DECS; + int retstat = 0; + size_t tsize = 0; + off_t toffset = 0; + uint32_t pflags = 0x00000000; + uint32_t pshare = 0x00000000; + uint32_t poptions = 0x00000000; + uint32_t pattributes = 0x00000000; + char fpath[PATH_MAX]; + struct fuse_file_info lfi; + struct fuse_file_info * fi = &lfi; + INTERIX_DEV_FILE ldf; + INTERIX_DEV_FILE * df = &ldf; + LOCAL_STREAM(s); + + MDBGLOG("rdpfs","\nrdpfs_mknod(path=\"%s\", mode=0%3o, dev=%lld)\n", path, mode, dev); + + g_memset(fpath,0,sizeof(char)*PATH_MAX); + g_memset(&lfi,0,sizeof(struct fuse_file_info)); + g_memset(&ldf,0,sizeof(INTERIX_DEV_FILE)); + + pflags |= FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES; + pshare |= (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE); + poptions |= FILE_NON_DIRECTORY_FILE; + + fi->flags |= O_WRONLY; + rdpfs_fullpath(fpath,path); + if (S_ISBLK(mode)) { + int64_t dmajor = major(dev); + int64_t dminor = minor(dev); + construct_INTERIX_DEV_FILE(df); + set_INTERIX_DEV_FILE(df, 'b', dmajor, dminor); + send_INTERIX_DEV_FILE(df, s); + s_mark_end(s); + tsize = s->end - s->data; + toffset = 0; + pattributes |= FILE_ATTRIBUTE_SYSTEM; + retstat = rdpfs_create_args(fpath,mode,fi,pflags,pshare,poptions,pattributes); + rdpfs_write_chunk(fpath,s->data,tsize,toffset,fi); + } + else if (S_ISCHR(mode)) { + int64_t dmajor = major(dev); + int64_t dminor = minor(dev); + construct_INTERIX_DEV_FILE(df); + set_INTERIX_DEV_FILE(df, 'c', dmajor, dminor); + send_INTERIX_DEV_FILE(df, s); + s_mark_end(s); + tsize = s->end - s->data; + toffset = 0; + pattributes |= FILE_ATTRIBUTE_SYSTEM; + retstat = rdpfs_create_args(fpath,mode,fi,pflags,pshare,poptions,pattributes); + rdpfs_write_chunk(fpath,s->data,tsize,toffset,fi); + } + else if (S_ISFIFO(mode)) { + tsize = 0; + toffset = 0; + pattributes |= FILE_ATTRIBUTE_SYSTEM; + retstat = rdpfs_create_args(fpath,mode,fi,pflags,pshare,poptions,pattributes); + } + else if (S_ISSOCK(mode)) { + tsize = 1; + toffset = 0; + pattributes |= FILE_ATTRIBUTE_SYSTEM; + retstat = rdpfs_create_args(fpath,mode,fi,pflags,pshare,poptions,pattributes); + rdpfs_write_chunk(fpath,s->data,tsize,toffset,fi); + } + else if (S_ISDIR(mode)) { + retstat = rdpfs_mkdir(fpath,mode); + } + else if (S_ISREG(mode)) { + pattributes = FILE_ATTRIBUTE_NORMAL; + retstat = rdpfs_create(fpath,mode,fi); + } + + if (fi != NULL && fi->fh > 0) { + rdpfs_release(fpath,fi); + } + + return retstat; +} + +/** Create a directory */ +static int rdpfs_mkdir(const char *path, mode_t mode) { + RDPFS_DECS; + //tbus fd = -1; + int retstat = 0; + char fpath[PATH_MAX]; + struct stream * s = NULL; + //struct stat st; + //ptrdiff_t idx = 0; + //tbus objs[1] = { 0x00000000 }; + //size_t num_objs = 0; + ptrdiff_t fsize = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + //tbus empty_fi = 0; + DR_DRIVE_CREATE_RSP iorsp; + struct fuse_file_info tfi; + struct fuse_file_info * lfi = NULL; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + uint32_t crc32 = 0; + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + MDBGLOG("rdpfs","\nrdpfs_mkdir(path=\"%s\", mode = %d)\n", path, mode); + + lfi = &tfi; + g_memset(&iorsp,0,sizeof(DR_DRIVE_CREATE_RSP)); + g_memset(lfi,0,sizeof(struct fuse_file_info)); + + cbdata = &(g_reqids[reqid]); + cbdata->userdata = (void *)(&iorsp); + rdpfs_fullpath(fpath,path); + + rdpfs_opcode = RDPFS_MKDIR; + fsize = g_strlen(fpath) + 1; + uniqid = reqid; + + if (fsize > 0 && fpath != NULL) { + crc32 = Crc32_ComputeBuf(0, fpath, fsize); + } + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, fsize); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + if (fsize > 0) { + out_uint8a(s, fpath, fsize); + } + s_mark_end(s); + MDBGLOG("rdpfs"," ** rdpfs_mkdir (about to send! fsize = %d; fpath = %s)", fsize, fpath); + fsize = s->end - s->data; + trans_force_write(pcon); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + MDBGLOG("rdpfs","sent."); + + MDBGLOG("rdpfs"," Entering wait loop..."); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_WAIT(lcv,lmutex); + MDBGLOG("rdpfs"," Finished."); + + lfi->fh = cbdata->FileId; + rdpfs_releasedir(path,lfi); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + MDBGLOG("rdpfs","ERROR [rdpfs_mkdir()]: cbdata->IoStatus.Value = 0x%8.8x; retstat = %d",cbdata->IoStatus.Value,retstat); + } + g_memset(cbdata,0,sizeof(callback)); + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + return retstat; +} + +/** Remove a file */ +int rdpfs_unlink(const char * path) { + RDPFS_DECS; + //tbus fd = -1; + int retstat = 0; + char fpath[PATH_MAX]; + struct stream * s = NULL; + //struct stat st; + //ptrdiff_t idx = 0; + //tbus objs[1] = { 0x00000000 }; + //size_t num_objs = 0; + ptrdiff_t fsize = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + //tbus empty_fi = 0; + uint32_t pflags = 0x00000000; + uint32_t pshare = 0x00000000; + uint32_t poptions = 0x00000000; + uint32_t pattributes = 0x00000000; + uint32_t crc32 = 0; + const uint32_t magic = RDP_PACKET_MAGIC; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + struct fuse_file_info tfi; + struct fuse_file_info * lfi = &tfi; + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + MDBGLOG("rdpfs","\nrdpfs_unlink(path=\"%s\")\n", path); + + g_memset(&tfi,0,sizeof(struct fuse_file_info)); + + cbdata = &(g_reqids[reqid]); + rdpfs_fullpath(fpath,path); + rdpfs_opcode = RDPFS_UNLINK; + fsize = g_strlen(fpath) + 1; + uniqid = reqid; + + pflags |= DELETE; + pshare |= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; + //poptions |= FILE_DELETE_ON_CLOSE; + rdpfs_open_args(fpath,lfi,pflags,pshare,poptions,pattributes); + fhandle = lfi->fh; + + if (fsize > 0 && fpath != NULL) { + crc32 = Crc32_ComputeBuf(0, fpath, fsize); + } + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, fsize); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + if (fsize > 0) { + out_uint8a(s, fpath, fsize); + } + s_mark_end(s); + MDBGLOG("rdpfs"," ** rdpfs_unlink (about to send! fsize = %d; fpath = %s)", fsize, fpath); + fsize = s->end - s->data; + trans_force_write(pcon); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + MDBGLOG("rdpfs","sent."); + + MDBGLOG("rdpfs"," Entering wait loop..."); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_WAIT(lcv,lmutex); + MDBGLOG("rdpfs"," Finished."); + + if (lfi != NULL && lfi->fh > 0) { + rdpfs_release(path,lfi); + } + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("rdpfs","ERROR [rdpfs_unlink()]: \"%s\" (cbdata->IoStatus.Value = 0x%8.8x; retstat = %d)",nterr,cbdata->IoStatus.Value,retstat); + //g_free(nterr); + } + + g_memset(cbdata,0,sizeof(callback)); + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + return retstat; +} + +/** Remove a directory */ +int rdpfs_rmdir(const char *path) { + RDPFS_DECS; + //tbus fd = -1; + int retstat = 0; + char fpath[PATH_MAX]; + struct stream * s = NULL; + //struct stat st; + //ptrdiff_t idx = 0; + //tbus objs[1] = { 0x00000000 }; + //size_t num_objs = 0; + ptrdiff_t fsize = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + //tbus empty_fi = 0; + uint32_t pflags = 0x00000000; + uint32_t pshare = 0x00000000; + uint32_t poptions = 0x00000000; + uint32_t pattributes = 0x00000000; + uint32_t crc32 = 0; + const uint32_t magic = RDP_PACKET_MAGIC; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + struct fuse_file_info tfi; + struct fuse_file_info * lfi = &tfi; + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + MDBGLOG("rdpfs","\nrdpfs_rmdir(path=\"%s\")\n", path); + + g_memset(&tfi,0,sizeof(struct fuse_file_info)); + + rdpfs_fullpath(fpath,path); + rdpfs_opcode = RDPFS_RMDIR; + fsize = g_strlen(fpath) + 1; + uniqid = reqid; + cbdata = &(g_reqids[reqid]); + + pflags |= DELETE; + pshare |= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; + poptions |= FILE_DELETE_ON_CLOSE; + retstat = rdpfs_open_args(fpath,lfi,pflags,pshare,poptions,pattributes); + if (retstat < 0) { + MDBGLOG("rdpfs","ERROR [rdpfs_rmdir()]: rdpfs_open_args() returned \"%d\"",retstat); + goto end; + } + fhandle = lfi->fh; + if (fhandle < 1) { + retstat = -EBADF; + MDBGLOG("rdpfs","ERROR [rdpfs_rmdir()]: bad file handle"); + goto end; + } + + if (fsize > 0 && fpath != NULL) { + crc32 = Crc32_ComputeBuf(0, fpath, fsize); + } + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, fsize); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + if (fsize > 0) { + out_uint8a(s, fpath, fsize); + } + s_mark_end(s); + MDBGLOG("rdpfs"," ** rdpfs_rmdir (about to send! fsize = %d; fpath = %s)", fsize, fpath); + fsize = s->end - s->data; + trans_force_write(pcon); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + MDBGLOG("rdpfs","sent."); + + MDBGLOG("rdpfs"," Entering wait loop..."); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_WAIT(lcv,lmutex); + MDBGLOG("rdpfs"," Finished."); + + if (lfi != NULL && lfi->fh > 0) { + rdpfs_release(path,lfi); + } + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("rdpfs","ERROR [rdpfs_rmdir()]: \"%s\" (cbdata->IoStatus.Value = 0x%8.8x; retstat = %d)",nterr,cbdata->IoStatus.Value,retstat); + //g_free(nterr); + } + + end: + g_memset(cbdata,0,sizeof(callback)); + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + return retstat; +} + +/** Create a symbolic link **/ +int rdpfs_symlink(const char * ipath, const char * ilink) { + RDPFS_DECS; + int retstat = 0; + int tres = 0; + char fpath[PATH_MAX] = ""; + //tbus fhandle = 0; + //int uniqid = 0; + mode_t mode = 0; + off_t toffset = 0; + size_t tsize = 0; + //ptrdiff_t wv = 0; + struct fuse_file_info lfi; + struct fuse_file_info * fi = &lfi; + MINSHALL_FRENCH_SYMLINK lsl; + MINSHALL_FRENCH_SYMLINK * sl = &lsl; + char * path = (char *)NULL; + char * link = (char *)NULL; + uint32_t pflags = 0x00000000; + uint32_t pshare = 0x00000000; + uint32_t poptions = 0x00000000; + uint32_t pattributes = 0x00000000; + LOCAL_STREAM(qs); + + path = (char *)g_strdup(ipath); + link = (char *)g_strdup(ilink); + + MDBGLOG("rdpfs","\nrdpfs_symlink(path=\"%s\", link=\"%s\")\n", path, link); + + if (path == NULL || link == NULL || g_strlen(path) < 1 || g_strlen(link) < 1) { + retstat = -EINVAL; + MDBGLOG("rdpfs","ERROR [rdpfs_symlink()]: either one or both of input arguments PATH or LINK is an empty string or a null pointer"); + goto end_tag; + } + + g_memset(fpath,0,sizeof(char)*PATH_MAX); + g_memset(fi,0,sizeof(struct fuse_file_info)); + g_memset(sl,0,sizeof(MINSHALL_FRENCH_SYMLINK)); + + construct_MINSHALL_FRENCH_SYMLINK(sl); + set_MINSHALL_FRENCH_SYMLINK(sl,path); + send_MINSHALL_FRENCH_SYMLINK(sl,qs); + s_mark_end(qs); + tsize = qs->end - qs->data; + + pflags |= FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES; + pshare |= (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE); + poptions |= FILE_NON_DIRECTORY_FILE; + pattributes |= FILE_ATTRIBUTE_SYSTEM; + + tres = rdpfs_create_args(link,mode,fi,pflags,pshare,poptions,pattributes); + if (fi == NULL || fi->fh < 1) { + retstat = -ENOENT; + goto end_tag; + } + if (tres < 0) { + MDBGLOG("rdpfs","ERROR [rdpfs_symlink()]: rdpfs_create_args() returned code \"%d\"",tres); + retstat = tres; + goto rel_tag; + } + + toffset = 0; + + tres = rdpfs_write(link, (const char *)(qs->data), tsize, toffset, fi); + if (tres < 0) { + MDBGLOG("rdpfs","ERROR [rdpfs_symlink()]: rdpfs_write() returned code \"%d\"",retstat); + retstat = tres; + } + + rel_tag: + rdpfs_release(link,fi); + + end_tag: + if (path != NULL) { + g_free(path); + } + if (link != NULL) { + g_free(link); + } + return retstat; +} + +/** Rename a file **/ +int rdpfs_rename(const char * path, const char * newpath) { + RDPFS_DECS; + //tbus fd = -1; + int retstat = 0; + char fpath[PATH_MAX]; + ptrdiff_t fsize = 0; + char npath[PATH_MAX]; + ptrdiff_t nsize = 0; + struct stream * s = NULL; + //struct stat st; + //ptrdiff_t idx = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + int ostat = 0; + size_t cnt = 0; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + uint32_t pflags = 0; + uint32_t pshare = 0; + uint32_t poptions = 0; + uint32_t pattributes = 0; + uint32_t crc32 = 0; + const uint32_t magic = RDP_PACKET_MAGIC; + struct fuse_file_info tfi; + struct fuse_file_info * lfi = &tfi; + + MDBGLOG("rdpfs","\nrdpfs_rename(path=\"%s\", newpath=\"%s\")\n", path, newpath); + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + g_memset(&tfi,0,sizeof(struct fuse_file_info)); + + cbdata = &(g_reqids[reqid]); + + lfi->flags |= O_RDWR; + pflags |= DELETE; + ostat = rdpfs_open_args(path,lfi,pflags,pshare,poptions,pattributes); + while (ostat < 0 && cnt < 5) { + g_sleep(1100); + ostat = rdpfs_open_args(path,lfi,pflags,pshare,poptions,pattributes); + cnt++; + } + fhandle = lfi->fh; + if (fhandle < 1) { + retstat = -ENOENT; + MDBGLOG("rdpfs","ERROR [rdpfs_rename()]: bad file handle"); + goto end; + } + + rdpfs_opcode = RDPFS_RENAME; + uniqid = reqid; + rdpfs_fullpath(fpath,path); + fsize = g_strlen(fpath) + 1; + rdpfs_fullpath(npath,newpath); + nsize = g_strlen(npath) + 1; + + if (nsize > 0 && npath != NULL) { + crc32 = Crc32_ComputeBuf(0, npath, nsize); + } + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, nsize); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + if (fsize > 0) { + out_uint8a(s, npath, nsize); + } + s_mark_end(s); + MDBGLOG("rdpfs"," ** rdpfs_rename (about to send! nsize = %d; npath = %s; pdu size = %d)", nsize, npath, (s->end - s->data)); + fsize = s->end - s->data; + trans_force_write(pcon); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + MDBGLOG("rdpfs","sent."); + + MDBGLOG("rdpfs"," Entering wait loop..."); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_WAIT(lcv,lmutex); + MDBGLOG("rdpfs"," Finished."); + + if (lfi != NULL && fhandle > 0) { + rdpfs_release(path,lfi); + } + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("rdpfs","ERROR [rdpfs_rename()]: \"%s\" (cbdata->IoStatus.Value = 0x%8.8x; retstat = %d)",nterr,cbdata->IoStatus.Value, retstat); + //g_free(nterr); + } + g_memset(cbdata,0,sizeof(callback)); + + end: + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + return retstat; +} + +/** Create a hard link to a file */ +int rdpfs_link(const char * path, const char * newpath) { + RDPFS_DECS; + int retstat = 0; + MDBGLOG("rdpfs","\nrdpfs_link(path=\"%s\", newpath=\"%s\")\n", path, newpath); + retstat = -EOPNOTSUPP; + return retstat; +} + +/** Change the permission bits of a file */ +int rdpfs_chmod(const char *path, mode_t mode) { + RDPFS_DECS; + int retstat = 0; + MDBGLOG("rdpfs","\nrdpfs_chmod(path=\"%s\", mode=0%03o)\n", path, mode); + return retstat; +} + +/** Change the owner and group of a file */ +int rdpfs_chown(const char *path, uid_t uid, gid_t gid) { + RDPFS_DECS; + int retstat = 0; + MDBGLOG("rdpfs","\nrdpfs_chown(path=\"%s\", uid=%d, gid=%d)\n", path, uid, gid); + return retstat; +} + +/** Change the size of a file */ +int rdpfs_truncate(const char * path, off_t newsize) { + RDPFS_DECS; + int retstat = 0; + struct fuse_file_info * lfi = NULL; + uint32_t pflags = 0x00000000; + uint32_t pshare = 0x00000000; + uint32_t poptions = 0x00000000; + uint32_t pattributes = 0x00000000; + + MDBGLOG("rdpfs","\nrdpfs_truncate(path=\"%s\", newsize=%lld)\n", path, newsize); + + lfi = (struct fuse_file_info *)g_malloc(sizeof(struct fuse_file_info), 1); + lfi->flags = O_WRONLY; + pflags |= FILE_WRITE_DATA; + + retstat = rdpfs_open_args(path, lfi, pflags, pshare, poptions, pattributes); + if (retstat < 0) { + goto end; + } + retstat = rdpfs_ftruncate(path, newsize, lfi); + rdpfs_release(path, lfi); + + end: + if (lfi != NULL) { + g_free(lfi); + } + + return retstat; +} + +/** Change the access and/or modification times of a file */ +/* note -- I'll want to change this as soon as 2.6 is in debian testing */ +int rdpfs_utime(const char * path, struct utimbuf * ubuf) { + RDPFS_DECS; + int retstat = 0; + //tbus fd = -1; + char fpath[PATH_MAX] = ""; + struct stream * s = NULL; + //struct stat st; + //ptrdiff_t idx = 0; + //tbus objs[1] = { 0x00000000 }; + //size_t num_objs = 0; + ptrdiff_t fsize = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + //tbus empty_fi = 0; + int ostat = 0; + size_t cnt = 0; + struct fuse_file_info * lfi = NULL; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + uint64_t actime = 0x0000000000000000; + uint64_t modtime = 0x0000000000000000; + //uint64_t creationtime = 0x0000000000000000; + //uint64_t changetime = 0x0000000000000000; + //uint32_t fileattributes = 0x00000000; + //uint32_t reserved = 0x00000000; + struct stat statbuf; + struct stat * sb = &statbuf; + uint32_t * p_crc32 = (uint32_t *)NULL; + uint32_t crc32 = 0; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + + g_memset(sb,0,sizeof(struct stat)); + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + MDBGLOG("rdpfs","\nrdpfs_utime(path=\"%s\")\n", path); + + cbdata = &(g_reqids[reqid]); + + lfi = (struct fuse_file_info *)g_malloc(sizeof(struct fuse_file_info), 1); + lfi->flags |= O_RDWR; + ostat = rdpfs_open(path,lfi); + while (ostat < 0 && cnt < 5) { + g_sleep(1100); + ostat = rdpfs_open(path,lfi); + cnt++; + } + fhandle = lfi->fh; + if (fhandle < 1) { + goto end; + } + rdpfs_fgetattr(path,sb,lfi); + actime = UnixToFileTime(ubuf->actime); + modtime = UnixToFileTime(ubuf->modtime); + + rdpfs_fullpath(fpath,path); + rdpfs_opcode = RDPFS_UTIME; + fsize = g_strlen(fpath) + 1; + uniqid = reqid; + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, fsize + 16); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + out_uint64_le(s, actime); + out_uint64_le(s, modtime); + if (fsize > 0) { + out_uint8a(s, fpath, fsize); + } + s_mark_end(s); + + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf(0, (void *)p, (size_t)(s->end - p)); + } + + MDBGLOG("rdpfs"," ** rdpfs_utime (about to send! fsize = %d; fpath = %s)", fsize, fpath); + fsize = s->end - s->data; + trans_force_write(pcon); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + MDBGLOG("rdpfs","sent."); + + MDBGLOG("rdpfs"," Entering wait loop..."); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_WAIT(lcv,lmutex); + MDBGLOG("rdpfs"," Finished."); + + if (lfi != NULL && fhandle > 0) { + rdpfs_release(path,lfi); + } + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + MDBGLOG("rdpfs","ERROR [rdpfs_utime()]: cbdata->IoStatus.Value = 0x%8.8x; retstat = %d",cbdata->IoStatus.Value, retstat); + } + g_memset(cbdata,0,sizeof(callback)); + + end: + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + if (lfi != NULL) { + g_free(lfi); + } + + return retstat; +} + +/** File open operation + * + * No creation, or truncation flags (O_CREAT, O_EXCL, O_TRUNC) + * will be passed to open(). Open should check if the operation + * is permitted for the given flags. Optionally open may also + * return an arbitrary filehandle in the fuse_file_info structure, + * which will be passed to all file operations. + * + * Changed in version 2.2 + */ +int rdpfs_open(const char * path, struct fuse_file_info * fi) { + RDPFS_DECS; + int retstat = 0; + //tbus fd = -1; + char fpath[PATH_MAX]; + struct stream * s = NULL; + char buf[512]; + struct stat st; + //ptrdiff_t idx = 0; + //tbus objs[1] = { 0x00000000 }; + //size_t num_objs = 0; + //int timeout = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + ptrdiff_t size = 0x00000000; + struct _rdpfs_data rdata; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + uint32_t pflags = 0x00000000; + uint32_t pshare = 0x00000000; + uint32_t poptions = 0x00000000; + uint32_t pattributes = 0x00000000; + uint32_t crc32 = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + struct stat lstatbuf; + struct stat * statbuf = &lstatbuf; + + MDBGLOG("rdpfs","\n\nrdpfs_open(path=\"%s\")\n",path); + + g_memset(&st,0,sizeof(struct stat)); + g_memset(fpath,0,sizeof(char)*PATH_MAX); + g_memset(buf,0,sizeof(char)*512); + g_memset(&rdata,0,sizeof(rdpfs_data)); + g_memset(statbuf,0,sizeof(struct stat)); + + rdpfs_fullpath(fpath, path); + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + get_cv_fs(reqid, &lcv,g_fs); + cbdata = &(g_reqids[reqid]); + + if ((fi->flags & O_ACCMODE) == O_RDONLY) { + pflags |= FILE_READ_DATA; + } + else if ((fi->flags & O_ACCMODE) == O_WRONLY) { + pflags |= FILE_WRITE_DATA; + } + else if ((fi->flags & O_ACCMODE) == O_RDWR) { + pflags |= (FILE_READ_DATA | FILE_WRITE_DATA); + } + else { + //pflags |= MAXIMUM_ALLOWED; + pflags = GENERIC_ALL; + } + + pshare |= (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE); + + rdpfs_opcode = RDPFS_OPEN; + size = g_strlen(fpath) + 1; + uniqid = reqid; + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, size + 16); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + out_uint32_le(s, pflags); + out_uint32_le(s, pshare); + out_uint32_le(s, poptions); + out_uint32_le(s, pattributes); + if (size > 0) { + out_uint8a(s, fpath, size); + } + s_mark_end(s); + size = s->end - s->data; + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf((uint32_t)0, (void *)p, (size_t)(s->end - p)); + } + + MDBGLOG("rdpfs"," ** rdpfs_open(): sending [g_fd = %d]", g_fd); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + MDBGLOG("rdpfs","sent."); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + + MDBGLOG("rdpfs","entering g_obj_wait loop:"); + TC_COND_WAIT(lcv, lmutex); + MDBGLOG("rdpfs","exiting g_obj_wait loop."); + + fhandle = cbdata->FileId; + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("rdpfs","ERROR [rdpfs_open()]: \"%s\" (retstat = %d; cbdata->IoStatus.Fields.Sev = 0x%8.8x)",nterr,retstat,cbdata->IoStatus.Value); + fhandle = -1; + } + fi->fh = fhandle; + //log_fi(fi); + + MDBGLOG("rdpfs","rdpfs_open(): done. (fi->fh = %d; fhandle = %d; retstat = %d)",fi->fh,fhandle,retstat); + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + return retstat; +} + +int rdpfs_open_args(const char * path, struct fuse_file_info * fi, uint32_t pflags, uint32_t pshare, uint32_t poptions, uint32_t pattributes) { + RDPFS_DECS; + int retstat = 0; + //tbus fd = -1; + char fpath[PATH_MAX]; + struct stream * s = NULL; + char buf[512]; + struct stat st; + //ptrdiff_t idx = 0; + //tbus objs[1] = { 0x00000000 }; + //size_t num_objs = 0; + //int timeout = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + ptrdiff_t size = 0x00000000; + struct _rdpfs_data rdata; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + struct stat lstatbuf; + struct stat * statbuf = &lstatbuf; + uint32_t crc32 = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + + MDBGLOG("rdpfs","\n\nrdpfs_open_args(path = \"%s\"; pflags = 0x%8.8x; pshare = 0x%8.8x; poptions = 0x%8.8x)\n",path,pflags,pshare,poptions); + + g_memset(&st,0,sizeof(struct stat)); + g_memset(fpath,0,sizeof(char)*PATH_MAX); + g_memset(buf,0,sizeof(char)*512); + g_memset(&rdata,0,sizeof(rdpfs_data)); + g_memset(statbuf,0,sizeof(struct stat)); + + rdpfs_fullpath(fpath, path); + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + get_cv_fs(reqid, &lcv,g_fs); + cbdata = &(g_reqids[reqid]); + + rdpfs_opcode = RDPFS_OPEN; + size = g_strlen(fpath) + 1; + uniqid = reqid; + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, size + 16); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + out_uint32_le(s, pflags); + out_uint32_le(s, pshare); + out_uint32_le(s, poptions); + out_uint32_le(s, pattributes); + if (size > 0) { + out_uint8a(s, fpath, size); + } + s_mark_end(s); + size = s->end - s->data; + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf((uint32_t)0, (void *)p, (size_t)(s->end - p)); + } + + MDBGLOG("rdpfs"," ** rdpfs_open_args(): sending [g_fd = %d]", g_fd); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + MDBGLOG("rdpfs","sent."); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + + MDBGLOG("rdpfs","entering g_obj_wait loop:"); + TC_COND_WAIT(lcv, lmutex); + MDBGLOG("rdpfs","exiting g_obj_wait loop."); + + fhandle = cbdata->FileId; + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("rdpfs","ERROR [rdpfs_open_args()]: \"%s\" (retstat = %d; cbdata->IoStatus.Fields.Sev = 0x%8.8x)",nterr,retstat,cbdata->IoStatus.Value); + fhandle = -1; + } + fi->fh = fhandle; + //log_fi(fi); + + MDBGLOG("rdpfs","rdpfs_open_args(): done. (fi->fh = %d; fhandle = %d; retstat = %d)",fi->fh,fhandle,retstat); + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + return retstat; +} + +/** Read data from an open file + * + * Read should return exactly the number of bytes requested except + * on EOF or error, otherwise the rest of the data will be + * substituted with zeroes. An exception to this is when the + * 'direct_io' mount option is specified, in which case the return + * value of the read system call will reflect the return value of + * this operation. + * + * Changed in version 2.2 + */ +// I don't fully understand the documentation above -- it doesn't +// match the documentation for the read() system call which says it +// can return with anything up to the amount of data requested. nor +// with the fusexmp code which returns the amount of data also +// returned by read. + +static int APP_CC rdpfs_read_chunk(const char * path, char * buf, size_t size, off_t offset, struct fuse_file_info * fi) { + RDPFS_DECS; + int retstat = 0; + //tbus fd = -1; + ptrdiff_t plen = 0; + char fpath[PATH_MAX]; + struct stream * s = NULL; + //struct stat st; + //ptrdiff_t idx = 0; + //tbus objs[1] = { 0x00000000 }; + //size_t num_objs = 0; + ptrdiff_t fsize = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + //tbus empty_fi = 0; + struct fuse_file_info * lfi = NULL; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + int mode = 0; + struct stat lstatbuf; + struct stat * statbuf = &lstatbuf; + uint32_t crc32 = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + plen = g_strlen(path); + if (path != NULL && plen > 0) { + g_strncpy(fpath,path,MIN(PATH_MAX - 1,plen)); + } + + lfi = fi; + fhandle = lfi->fh; + mode = lfi->flags & O_ACCMODE; + + MDBGLOG("rdpfs","\nINFO\t[%s()]: called (path=\"%s\", buf=0x%8.8x, size=%d, offset=%llu, fi=0x%8.8x, lfi=0x%8.8x, statbuf->st_size = %d, mode = 0x%8.8x, O_RDONLY = %d, O_RDWR = %d, O_WRONLY = %d)\n", + __func__, path, buf, size, offset, fi, lfi, statbuf->st_size, + mode, (mode & O_RDONLY), (mode & O_RDWR), (mode & O_WRONLY)); + + cbdata = &(g_reqids[reqid]); + cbdata->userdata = (unsigned char *)buf; + if (g_fs != NULL) { + device_id = g_fs->device_id; + cbdata->fs = g_fs; + } + cbdata->device_id = device_id; + + rdpfs_opcode = RDPFS_READ; + fsize = g_strlen(fpath) + 1; + uniqid = reqid; + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, fsize + 12); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + out_uint32_le(s, size); + out_uint64_le(s, offset); + if (fsize > 0) { + out_uint8a(s, fpath, fsize); + } + s_mark_end(s); + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf((uint32_t)0, (void *)p, (size_t)(s->end - p)); + } + MDBGLOG("rdpfs"," ** rdpfs_read_chunk (about to send! size = %d; fsize = %d; offset = %lu; fpath = %s)", size, fsize, offset, fpath); + fsize = s->end - s->data; + trans_force_write(pcon); + g_memset(s->data,0,sizeof(char)*MAX_STREAM); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + MDBGLOG("rdpfs","sent."); + + MDBGLOG("rdpfs"," Entering wait loop..."); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_WAIT(lcv,lmutex); + MDBGLOG("rdpfs"," Finished."); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + const char * nterr = (const char *)ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("rdpfs","ERROR [rdpfs_read_chunk()]: \"%s\" (retstat = %d; cbdata->IoStatus.Value = 0x%8.8x)",nterr,retstat,cbdata->IoStatus.Value); + //retstat = 0; + } + else { + retstat = cbdata->length; + } + g_memset(cbdata,0,sizeof(callback)); + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + return retstat; +} + +int rdpfs_read(const char * path, char * buf, size_t size, off_t offset, struct fuse_file_info * fi) { + RDPFS_DECS; + #ifndef CHUNK_SIZE + #define CHUNK_SIZE 4096 + #endif + //tbus fd = -1; + int retstat = 0; + char fpath[PATH_MAX]; + //struct stream * s = NULL; + //struct stat st; + ptrdiff_t idx = 0; + //tbus objs[1] = { 0x00000000 }; + //size_t num_objs = 0; + //ptrdiff_t fsize = 0; + //struct trans * pcon = (struct trans *)NULL; + //int rdpfs_opcode = 0x00000000; + //int reqid = -1; + tbus fhandle = 0; + //int uniqid = 0; + //tbus empty_fi = 0; + struct fuse_file_info * lfi = NULL; + //tc_p lmutex = (tc_p)NULL; + //tc_p lcv = (tc_p)NULL; + //callback * cbdata = NULL; + int mode = 0; + struct stat lstatbuf; + struct stat * statbuf = &lstatbuf; + size_t chunks = 0; + char * tpos = (char *)NULL; + off_t toffset = 0; + size_t tsize = 0; + uint64_t tally = 0; + + g_memset(statbuf,0,sizeof(struct stat)); + + lfi = fi; + fhandle = lfi->fh; + mode = lfi->flags & O_ACCMODE; + rdpfs_fgetattr(path,statbuf,lfi); + rdpfs_fullpath(fpath,path); + + MDBGLOG("rdpfs","\nrdpfs_read(path=\"%s\", buf=0x%8.8x, size=%d, offset=%llu, fi=0x%8.8x, lfi=0x%8.8x, statbuf->st_size = %d, mode = 0x%8.8x, O_RDONLY = %d, O_RDWR = %d, O_WRONLY = %d)\n", + path, buf, size, offset, fi, lfi, statbuf->st_size, + mode, (mode & O_RDONLY), (mode & O_RDWR), (mode & O_WRONLY)); + + if (size > statbuf->st_size) { + size = statbuf->st_size; + } + + chunks = (size == 0) ? 0 : 1; + if (size > CHUNK_SIZE) { + chunks = ((size % CHUNK_SIZE) == 0) ? size / CHUNK_SIZE : (size / CHUNK_SIZE) + 1; + } + + for (idx = 0; idx < chunks; idx++) { + tpos = buf + (idx * CHUNK_SIZE); + toffset = offset + (idx * CHUNK_SIZE); + tsize = (idx == (chunks - 1) && (size % CHUNK_SIZE) != 0) ? size % CHUNK_SIZE : CHUNK_SIZE; + retstat = rdpfs_read_chunk(fpath,tpos,tsize,toffset,lfi); + if (retstat < 0) { + break; + } + else { + tally += retstat; + } + } + if (retstat > -1) { + retstat = tally; + } + + return retstat; +} + +/** Write data to an open file + * + * Write should return exactly the number of bytes requested + * except on error. An exception to this is when the 'direct_io' + * mount option is specified (see read operation). + * + * Changed in version 2.2 + */ +static int rdpfs_write_chunk(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { + RDPFS_DECS; + //tbus fd = -1; + int retstat = 0; + char fpath[PATH_MAX]; + struct stream * s = NULL; + //struct stat st; + //ptrdiff_t idx = 0; + //tbus objs[1] = { 0x00000000 }; + //size_t num_objs = 0; + ptrdiff_t fsize = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + tbus empty_fi = 0; + struct fuse_file_info * lfi = NULL; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + uint32_t crc32 = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + + lfi = fi; + fhandle = lfi->fh; + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + MDBGLOG("rdpfs","\nrdpfs_write_chunk(path=\"%s\", buf=0x%8.8x, size=%d, offset=%lld, fi=0x%8.8x)\n", + path, buf, size, offset, fi); + + cbdata = &(g_reqids[reqid]); + cbdata->userdata = (unsigned char *)buf; + + rdpfs_fullpath(fpath,path); + + rdpfs_opcode = RDPFS_WRITE; + fsize = g_strlen(fpath) + 1; + uniqid = reqid; + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, (fsize + size + 12)); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + out_uint32_le(s, size); + out_uint64_le(s, offset); + if (fsize > 0) { + out_uint8a(s, fpath, fsize); + } + if (size > 0) { + out_uint8a(s, buf, size); + } + s_mark_end(s); + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf(0, (void *)p, (size_t)(s->end - p)); + } + MDBGLOG("rdpfs"," ** rdpfs_write_chunk (about to send! size = %d; fsize = %d; offset = %lu; fpath = %s)", size, fsize, offset, fpath); + fsize = s->end - s->data; + trans_force_write(pcon); + g_memset(s->data,0,sizeof(char)*MAX_STREAM); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + MDBGLOG("rdpfs","sent."); + + MDBGLOG("rdpfs"," Entering wait loop..."); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_WAIT(lcv,lmutex); + MDBGLOG("rdpfs"," Finished."); + + if (empty_fi > 0 && lfi != NULL) { + rdpfs_release(path,lfi); + } + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + MDBGLOG("rdpfs","ERROR [rdpfs_write_chunk()]: retstat = %d; cbdata->IoStatus.Value = %d",retstat,cbdata->IoStatus.Value); + } + else { + retstat = cbdata->length; + } + g_memset(cbdata,0,sizeof(callback)); + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + return retstat; +} + +static int rdpfs_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { + RDPFS_DECS; + #ifndef CHUNK_SIZE + #define CHUNK_SIZE 4096 + #endif + //tbus fd = -1; + int retstat = 0; + char fpath[PATH_MAX]; + //struct stream * s = NULL; + ptrdiff_t idx = 0; + //ptrdiff_t fsize = 0; + //struct trans * pcon = (struct trans *)NULL; + //int rdpfs_opcode = 0x00000000; + //int reqid = -1; + tbus fhandle = 0; + //int uniqid = 0; + //tbus empty_fi = 0; + struct fuse_file_info * lfi = NULL; + //tc_p lmutex = (tc_p)NULL; + //tc_p lcv = (tc_p)NULL; + //callback * cbdata = NULL; + int mode = 0; + size_t chunks = 0; + char * tpos = (char *)NULL; + off_t toffset = 0; + size_t tsize = 0; + uint64_t tally = 0; + + lfi = fi; + fhandle = lfi->fh; + mode = lfi->flags & O_ACCMODE; + rdpfs_fullpath(fpath,path); + + MDBGLOG("rdpfs","\nrdpfs_write(path=\"%s\", buf=0x%8.8x, size=%d, offset=%llu, fi=0x%8.8x, lfi=0x%8.8x, mode = 0x%8.8x, O_RDONLY = %d, O_RDWR = %d, O_WRONLY = %d)\n", + path, buf, size, offset, fi, lfi, + mode, (mode & O_RDONLY), (mode & O_RDWR), (mode & O_WRONLY)); + + chunks = (size == 0) ? 0 : 1; + if (size > CHUNK_SIZE) { + chunks = ((size % CHUNK_SIZE) == 0) ? size / CHUNK_SIZE : (size / CHUNK_SIZE) + 1; + } + + for (idx = 0; idx < chunks; idx++) { + tpos = (char *)buf + (idx * CHUNK_SIZE); + toffset = offset + (idx * CHUNK_SIZE); + tsize = (idx == (chunks - 1) && (size % CHUNK_SIZE) != 0) ? size % CHUNK_SIZE : CHUNK_SIZE; + retstat = rdpfs_write_chunk(path,tpos,tsize,toffset,lfi); + if (retstat < 0) { + break; + } + else { + tally += retstat; + } + } + if (retstat > -1) { + retstat = tally; + } + + return retstat; +} + + +/** Get file system statistics + * + * The 'f_frsize', 'f_favail', 'f_fsid' and 'f_flag' fields are ignored + * + * Replaced 'struct statfs' parameter with 'struct statvfs' in + * version 2.5 + */ +int rdpfs_statfs(const char *path, struct statvfs *statv) { + RDPFS_DECS; + //tbus fd = -1; + int retstat = 0; + char fpath[PATH_MAX]; + struct stream * s = NULL; + //struct stat st; + //ptrdiff_t idx = 0; + //tbus objs[1] = { 0x00000000 }; + //size_t num_objs = 0; + ptrdiff_t fsize = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + //tbus empty_fi = 0; + struct fuse_file_info * lfi = NULL; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + FILE_FS_FULL_SIZE_INFORMATION * vbuf = (FILE_FS_FULL_SIZE_INFORMATION *)NULL; + int bytes_per_sector = 0; + int sectors_per_block = 0; + int bytes_per_block = 0; + uint32_t crc32 = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + MDBGLOG("rdpfs","\nrdpfs_statfs(path=\"%s\")\n", + path); + + cbdata = &(g_reqids[reqid]); + cbdata->userdata = (void *)g_malloc(sizeof(FILE_FS_FULL_SIZE_INFORMATION), 1); + vbuf = (FILE_FS_FULL_SIZE_INFORMATION *)(cbdata->userdata); + + rdpfs_fullpath(fpath,path); + + lfi = (struct fuse_file_info *)g_malloc(sizeof(struct fuse_file_info), 1); + rdpfs_open(path, lfi); + fhandle = lfi->fh; + + rdpfs_opcode = RDPFS_STATFS; + fsize = g_strlen(fpath) + 1; + uniqid = reqid; + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, fsize); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + if (fsize > 0) { + out_uint8a(s, fpath, fsize); + } + s_mark_end(s); + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf(0, (void *)p, (size_t)(s->end - p)); + } + MDBGLOG("rdpfs"," ** rdpfs_statfs (about to send! fsize = %d; fpath = %s)", fsize, fpath); + fsize = s->end - s->data; + trans_force_write(pcon); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + MDBGLOG("rdpfs","sent."); + + MDBGLOG("rdpfs"," Entering wait loop..."); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_WAIT(lcv,lmutex); + MDBGLOG("rdpfs"," Finished."); + + bytes_per_sector = vbuf->BytesPerSector; + sectors_per_block = vbuf->SectorsPerAllocationUnit; + bytes_per_block = bytes_per_sector * sectors_per_block; + + statv->f_bsize = bytes_per_block; + statv->f_blocks = vbuf->TotalAllocationUnits; + statv->f_bfree = vbuf->ActualAvailableAllocationUnits; + statv->f_bavail = vbuf->CallerAvailableAllocationUnits; + statv->f_files = statv->f_ffree = statv->f_favail = 0xffffffff; + statv->f_namemax = 255; + + MDBGLOG("rdpfs","STATFS: f_bsize = %d; f_blocks = %d; f_bfree = %d; f_bavail = %d; f_files = %d",statv->f_bsize,statv->f_blocks,statv->f_bfree,statv->f_bavail,statv->f_files); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + MDBGLOG("rdpfs","ERROR [rdpfs_statfs()]: cbdata->IoStatus.Fields.Sev == STATUS_SEVERITY_ERROR (cbdata->IoStatus.Value = 0x%8.8x)",cbdata->IoStatus.Value); + } + else { + retstat = 0; + } + if (cbdata->userdata != NULL) { + g_free(cbdata->userdata); + } + g_memset(cbdata,0,sizeof(callback)); + if (lfi != NULL) { + g_free(lfi); + } + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + return retstat; +} + +/** Possibly flush cached data + * + * BIG NOTE: This is not equivalent to fsync(). It's not a + * request to sync dirty data. + * + * Flush is called on each close() of a file descriptor. So if a + * filesystem wants to return write errors in close() and the file + * has cached dirty data, this is a good place to write back data + * and return any errors. Since many applications ignore close() + * errors this is not always useful. + * + * NOTE: The flush() method may be called more than once for each + * open(). This happens if more than one file descriptor refers + * to an opened file due to dup(), dup2() or fork() calls. It is + * not possible to determine if a flush is final, so each flush + * should be treated equally. Multiple write-flush sequences are + * relatively rare, so this shouldn't be a problem. + * + * Filesystems shouldn't assume that flush will always be called + * after some writes, or that if will be called at all. + * + * Changed in version 2.2 + */ +int rdpfs_flush(const char * path, struct fuse_file_info * fi) { + RDPFS_DECS; + //tbus fd = -1; + int retstat = 0; + char fpath[PATH_MAX]; + struct stream * s = NULL; + //struct stat st; + //ptrdiff_t idx = 0; + //tbus objs[1] = { 0x00000000 }; + //size_t num_objs = 0; + ptrdiff_t fsize = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + tbus empty_fi = 0; + struct fuse_file_info * lfi = NULL; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + uint32_t crc32 = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + MDBGLOG("rdpfs","\nrdpfs_flush(path=\"%s\", fi=0x%8.8x)\n", path, fi); + + cbdata = &(g_reqids[reqid]); + + rdpfs_fullpath(fpath,path); + + if (fi == NULL || fi->fh < 1) { + empty_fi = 1; + lfi = (struct fuse_file_info *)g_malloc(sizeof(struct fuse_file_info), 1); + g_memcpy(lfi,fi,sizeof(struct fuse_file_info)); + rdpfs_open(path,lfi); + } + else { + lfi = fi; + } + fhandle = lfi->fh; + + rdpfs_opcode = RDPFS_FLUSH; + fsize = g_strlen(fpath) + 1; + uniqid = reqid; + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, fsize); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + if (fsize > 0) { + out_uint8a(s, fpath, fsize); + } + s_mark_end(s); + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf(0, (void *)p, (size_t)(s->end - p)); + } + MDBGLOG("rdpfs"," ** rdpfs_flush (about to send! fsize = %d; fpath = %s)", fsize, fpath); + fsize = s->end - s->data; + trans_force_write(pcon); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + MDBGLOG("rdpfs","sent."); + + MDBGLOG("rdpfs"," Entering wait loop..."); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_WAIT(lcv,lmutex); + MDBGLOG("rdpfs"," Finished."); + + if (empty_fi > 0 && lfi != NULL) { + rdpfs_release(path,lfi); + } + + if (cbdata->IoStatus.Fields.Sev == STATUS_SEVERITY_ERROR) { + MDBGLOG("rdpfs","ERROR [rdpfs_flush()]: cbdata->IoStatus.Fields.Sev == STATUS_SEVERITY_ERROR (cbdata->IoStatus.Value = 0x%8.8x)",cbdata->IoStatus.Value); + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + } + else { + retstat = cbdata->length; + } + if (cbdata->userdata != NULL) { + g_free(cbdata->userdata); + } + g_memset(cbdata,0,sizeof(callback)); + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + if (empty_fi > 0 && lfi != NULL) { + g_free(lfi); + } + + return retstat; +} + +/** Release an open file + * + * Release is called when there are no more references to an open + * file: all file descriptors are closed and all memory mappings + * are unmapped. + * + * For every open() call there will be exactly one release() call + * with the same flags and file descriptor. It is possible to + * have a file opened more than once, in which case only the last + * release will mean, that no more reads/writes will happen on the + * file. The return value of release is ignored. + * + * Changed in version 2.2 + */ +int rdpfs_release(const char * path, struct fuse_file_info * fi) { + RDPFS_DECS; + int retstat = 0; + char fpath[PATH_MAX]; + struct stream * s = NULL; + char buf[512]; + struct stat st; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + ptrdiff_t size = 0x00000000; + struct _rdpfs_data rdata; + tbus fhandle = 0; + int uniqid = 0; + int reqid = -1; + callback * cbdata = NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + uint32_t crc32 = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *)&lmut,g_fs); + TC_MUTEX_LOCK(lmut); + TC_MUTEX_UNLOCK(mutex_fsop); + + MDBGLOG("rdpfs","\n\nrdpfs_release(path=\"%s\")\n",path); + g_memset(&st,0,sizeof(struct stat)); + g_memset(fpath,0,sizeof(char)*PATH_MAX); + g_memset(buf,0,sizeof(char)*512); + g_memset(&rdata,0,sizeof(rdpfs_data)); + + rdpfs_fullpath(fpath, path); + + rdpfs_opcode = RDPFS_RELEASE; + size = g_strlen(fpath) + 1; + uniqid = reqid; + fhandle = fi->fh; + cbdata = &(g_reqids[reqid]); + cbdata->FileId = fhandle; + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, size); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + if (size > 0) { + out_uint8a(s, fpath, size); + } + s_mark_end(s); + size = s->end - s->data; + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf(0, (void *)p, (size_t)(s->end - p)); + } + MDBGLOG("rdpfs"," ** rdpfs_release(): sending [g_fd = %d]", g_fd); + trans_force_write(pcon); + MDBGLOG("rdpfs","sent."); + g_memset(s->data,0,MAX_STREAM); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + + get_cv_fs(reqid,&lcv,g_fs); + MDBGLOG("rdpfs"," Waiting..."); + TC_COND_WAIT(lcv,lmut); + MDBGLOG("rdpfs"," Done."); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + retstat = rdpfs_error("rdpfs_release lstat"); + MDBGLOG("rdpfs","ERROR [rdpfs_release()]: retstat = %d",retstat); + } + //log_fi(fi); + + MDBGLOG("rdpfs","rdpfs_release(): done. ()"); + + TC_MUTEX_UNLOCK(lmut); + free_reqid_fs(reqid); + + return retstat; +} + +/** Synchronize file contents + * + * If the datasync parameter is non-zero, then only the user data + * should be flushed, not the meta data. + * + * Changed in version 2.2 + */ +int rdpfs_fsync(const char * path, int datasync, struct fuse_file_info * fi) { + RDPFS_DECS; + int retstat = 0; + //tbus fhandle = 0; + //int uniqid = 0; + + MDBGLOG("rdpfs","\nrdpfs_fsync(path=\"%s\", datasync=%d, fi=0x%08x)\n", + path, datasync, fi); + //log_fi(fi); + + if (datasync) + retstat = fdatasync(fi->fh); + else + retstat = fsync(fi->fh); + + if (retstat < 0) + rdpfs_error("rdpfs_fsync fsync"); + + return retstat; +} + +#if defined(__linux__) +/** Set extended attributes */ +int rdpfs_setxattr(const char *path, const char *name, const char *value, size_t size, int flags) { + RDPFS_DECS; + int retstat = 0; + char fpath[PATH_MAX]; + //tbus fhandle = 0; + //int uniqid = 0; + + MDBGLOG("rdpfs","\nrdpfs_setxattr(path=\"%s\", name=\"%s\", value=\"%s\", size=%d, flags=0x%08x)\n", + path, name, value, size, flags); + g_memset(fpath,0,sizeof(char)*PATH_MAX); + rdpfs_fullpath(fpath, path); + + //retstat = lsetxattr(fpath, name, value, size, flags); + if (retstat < 0) + retstat = rdpfs_error("rdpfs_setxattr lsetxattr"); + + return retstat; +} + +/** Get extended attributes */ +int rdpfs_getxattr(const char * ipath, const char * iname, char * ivalue, size_t size) { + RDPFS_DECS; + int retstat = 0; + char fpath[PATH_MAX]; + //tbus fhandle = 0; + //int uniqid = 0; + char * path = (char *)NULL; + char * name = (char *)NULL; + char * value = (char *)NULL; + struct fuse_file_info lfi; + struct fuse_file_info * fi = &lfi; + FILE_OBJECTID_BUFFER lbuf; + RETRIEVAL_POINTERS_BUFFER lrpn; + void * buf = NULL; + + path = (char *)g_strdup(ipath); + name = (char *)g_strdup(iname); + value = (char *)g_strdup(ivalue); + + MDBGLOG("rdpfs","\nrdpfs_getxattr(path = \"%s\", name = \"%s\", value = \"%s\", size = %d)\n", path, name, value, size); + + g_memset(&lbuf,0,sizeof(FILE_OBJECTID_BUFFER)); + g_memset(&lrpn,0,sizeof(RETRIEVAL_POINTERS_BUFFER)); + g_memset(&lfi,0,sizeof(struct fuse_file_info)); + g_memset(fpath,0,sizeof(char)*PATH_MAX); + rdpfs_fullpath(fpath, path); + + fi->flags |= O_RDONLY; + rdpfs_open(path, fi); + + if (!g_strcasecmp(name,"oid")) { + char tmp[20] = ""; + const uint32_t cmd = FSCTL_GET_OBJECT_ID; + g_memset(tmp,0,sizeof(char) * 20); + buf = &lbuf; + rdpfs_fsctl(path,fi,cmd,0,buf); + g_snprintf(tmp,19,"0x%8.8x",((BYTE *)buf)[0]); + g_memcpy(ivalue,tmp,MIN(20,size)); + } + else if (!g_strcasecmp(name,"mft")) { + char tmp[20] = ""; + const uint32_t cmd = FSCTL_GET_RETRIEVAL_POINTERS; + BYTE tout[128]; + QWORD blah = 5; + g_memset(tmp,0,sizeof(char) * 20); + g_memset(tout,0,sizeof(BYTE) * 128); + g_memcpy(tout,&blah,8); + buf = tout; + rdpfs_fsctl(path,fi,cmd,8,buf); + g_snprintf(tmp,19,"0x%8.8x",((BYTE *)buf)[0]); + g_memcpy(ivalue,tmp,MIN(20,size)); + g_memcpy(&lrpn,buf,32); + MDBGLOG("rdpfs"," ** RESULTS: ExtentCount = %d; StartingVcn = %lld",lrpn.ExtentCount,lrpn.StartingVcn); + } + + rdpfs_release(path, fi); + + MDBGLOG("rdpfs","rdpfs_getxattr(): value = \"%s\"\n", value); + + return retstat; +} + +/** List extended attributes */ +int rdpfs_listxattr(const char *path, char *list, size_t size) { + RDPFS_DECS; + int retstat = 0; + char fpath[PATH_MAX]; + char *ptr; + //tbus fhandle = 0; + //int uniqid = 0; + + MDBGLOG("rdpfs","rdpfs_listxattr(path=\"%s\", list=0x%08x, size=%d)\n", + path, list, size + ); + g_memset(fpath,0,sizeof(char)*PATH_MAX); + rdpfs_fullpath(fpath, path); + + //retstat = llistxattr(fpath, list, size); + if (retstat < 0) + retstat = rdpfs_error("rdpfs_listxattr llistxattr"); + + MDBGLOG("rdpfs"," returned attributes (length %d):\n", retstat); + for (ptr = list; ptr < list + retstat; ptr += strlen(ptr)+1) + MDBGLOG("rdpfs"," \"%s\"\n", ptr); + + return retstat; +} + +/** Remove extended attributes */ +int rdpfs_removexattr(const char *path, const char *name) { + RDPFS_DECS; + int retstat = 0; + char fpath[PATH_MAX]; + //tbus fhandle = 0; + //int uniqid = 0; + + MDBGLOG("rdpfs","\nrdpfs_removexattr(path=\"%s\", name=\"%s\")\n", + path, name); + g_memset(fpath,0,sizeof(char)*PATH_MAX); + rdpfs_fullpath(fpath, path); + + //retstat = lremovexattr(fpath, name); + if (retstat < 0) + retstat = rdpfs_error("rdpfs_removexattr lrmovexattr"); + + return retstat; +} +#endif + +/** Open directory + * + * This method should check if the open operation is permitted for + * this directory + * + * Introduced in version 2.3 + */ +int rdpfs_opendir(const char * path, struct fuse_file_info * fi) { + RDPFS_DECS; + int retstat = 0; + //tbus fd = -1; + char fpath[PATH_MAX]; + struct stream * s = NULL; + char buf[512]; + struct stat st; + //ptrdiff_t idx = 0; + //tbus objs[1] = { 0x00000000 }; + //size_t num_objs = 0; + //int timeout = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + ptrdiff_t size = 0x00000000; + struct _rdpfs_data rdata; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + uint32_t crc32 = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + MDBGLOG("rdpfs","\n\nrdpfs_opendir(path=\"%s\")\n",path); + + g_memset(&st,0,sizeof(struct stat)); + g_memset(fpath,0,sizeof(char)*PATH_MAX); + g_memset(buf,0,sizeof(char)*512); + g_memset(&rdata,0,sizeof(rdpfs_data)); + + rdpfs_fullpath(fpath, path); + + get_cv_fs(reqid, &lcv,g_fs); + cbdata = &(g_reqids[reqid]); + + rdpfs_opcode = RDPFS_OPENDIR; + size = g_strlen(fpath) + 1; + uniqid = reqid; + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, size); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + if (size > 0) { + out_uint8a(s, fpath, size); + } + s_mark_end(s); + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf(0, (void *)p, (size_t)(s->end - p)); + } + size = s->end - s->data; + + MDBGLOG("rdpfs"," ** rdpfs_opendir(): sending [g_fd = %d]", g_fd); + trans_force_write(pcon); + MDBGLOG("rdpfs","sent."); + g_memset(s->data,0,MAX_STREAM); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + + MDBGLOG("rdpfs","entering g_obj_wait loop:"); + TC_COND_WAIT(lcv, lmutex); + MDBGLOG("rdpfs","exiting g_obj_wait loop."); + + fhandle = cbdata->FileId; + + if (retstat != 0) { + retstat = rdpfs_error("rdpfs_opendir lstat"); + MDBGLOG("rdpfs","ERROR [rdpfs_opendir()]: retstat = %d",retstat); + } + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + MDBGLOG("rdpfs","ERROR [rdpfs_opendir()]: retstat = %d; cbdata->IoStatus.Value = 0x%8.8x",retstat,cbdata->IoStatus.Value); + } + fi->fh = fhandle; + //log_fi(fi); + + MDBGLOG("rdpfs","rdpfs_opendir(): done. (fi->fh = %d; retstat = %d)",fi->fh,retstat); + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + return retstat; +} + +/** Read directory + * + * This supersedes the old getdir() interface. New applications + * should use this. + * + * The filesystem may choose between two modes of operation: + * + * 1) The readdir implementation ignores the offset parameter, and + * passes zero to the filler function's offset. The filler + * function will not return '1' (unless an error happens), so the + * whole directory is read in a single readdir operation. This + * works just like the old getdir() method. + * + * 2) The readdir implementation keeps track of the offsets of the + * directory entries. It uses the offset parameter and always + * passes non-zero offset to the filler function. When the buffer + * is full (or an error happens) the filler function will return + * '1'. + * + * Introduced in version 2.3 + */ +int rdpfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { + RDPFS_DECS; + int retstat = 0; + //tbus fd = -1; + DIR * dp = (DIR *)NULL; + char fpath[PATH_MAX]; + struct stream * s = NULL; + struct stat st; + ptrdiff_t idx = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + ptrdiff_t size = 0x00000000; + struct fuse_file_info * lfi = (struct fuse_file_info *)NULL; + callback * cbdata = (callback *)NULL; + filelist * lst = (filelist *)NULL; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + tbus empty_fi_fh = 0; + uint32_t crc32 = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + + /* */ + /* lock access by other threads: */ + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + MDBGLOG("rdpfs","\n\nrdpfs_readdir(path=\"%s\")\n",path); + g_memset(&st,0,sizeof(struct stat)); + g_memset(fpath,0,sizeof(char)*PATH_MAX); + + rdpfs_opcode = RDPFS_READDIR; + uniqid = reqid; + + cbdata = (callback *)(&(g_reqids[reqid])); + cbdata->opid = reqid; + cbdata->uniqid = uniqid; + cbdata->opcode = rdpfs_opcode; + cbdata->fs = g_fs; + cbdata->trans = (cbdata->fs == NULL) ? (struct trans *)NULL : cbdata->fs->ccon; + cbdata->fd = (cbdata->trans == NULL) ? -1 : cbdata->trans->sck; + cbdata->type = (cbdata->trans == NULL) ? 0 : -1; + cbdata->length = sizeof(filelist); + cbdata->userdata = (BYTE *)g_malloc(sizeof(BYTE) * cbdata->length, 1); + idx = g_strlen(path); + lst = (filelist *)(cbdata->userdata); + g_memcpy(cbdata->fname,path,(idx > 511)?511:idx); + if (fi != NULL) { + dp = (DIR *)(uintptr_t) fi->fh; + } + else { + empty_fi_fh = 1; + lfi = (struct fuse_file_info *)g_malloc(sizeof(struct fuse_file_info), 1); + rdpfs_opendir(path, lfi); + dp = (DIR *)(uintptr_t) lfi->fh; + } + rdpfs_fullpath(fpath,path); + fhandle = (int)(uintptr_t)dp; + cbdata->FileId = fhandle; + size = g_strlen(fpath) + 1; + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, size); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + if (size > 0) { + out_uint8a(s, fpath, size); + } + s_mark_end(s); + size = s->end - s->data; + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf(0, (void *)p, (size_t)(s->end - p)); + } + pcon->callback_data = (void *)(cbdata); + MDBGLOG("rdpfs"," ** rdpfs_readdir(): sending [g_fd = %d; fhandle = %d]", g_fd, fhandle); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + MDBGLOG("rdpfs","sent."); + + MDBGLOG("rdpfs","INFO\t[%s()]: entering g_obj_wait loop:", __func__); + get_cv_fs(reqid, &lcv,g_fs); + TC_COND_WAIT(lcv, lmutex); + MDBGLOG("rdpfs","INFO\t[%s()]: exiting g_obj_wait loop. (lst->count = %d)", __func__, lst->count); + + filler(buf, ".", NULL, 0); + filler(buf, "..", NULL, 0); + for (idx = 0; idx < lst->count; idx++) { + char * tfname = (char *)NULL; + struct stat tst; + struct stat * st = &tst; + if (lst->files[idx]->filename != NULL && g_strlen(lst->files[idx]->filename) > 0 && (lst->files[idx]->filename)[0] != '.') { + tfname = lst->files[idx]->filename; + } + if (tfname != NULL) { + g_memset(&tst,0,sizeof(struct stat)); + st->st_dev = 0x00000801; + if ((lst->files[idx]->FileAttributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY) { + st->st_mode = 0644; + } + else { + st->st_mode = 0755; + } + st->st_ctime = FileTimeToUnix(lst->files[idx]->CreationTime); + st->st_mtime = FileTimeToUnix(lst->files[idx]->LastWriteTime); + st->st_atime = FileTimeToUnix(lst->files[idx]->LastAccessTime); + st->st_size = lst->files[idx]->EndOfFile; + st->st_blocks = lst->files[idx]->AllocationSize; + if (lst->files[idx]->Directory > 0) { + /* set the "directory" flag: */ + st->st_mode |= S_IFDIR; + st->st_nlink = 1; + } + else if ((lst->files[idx]->FileAttributes & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM && rdpfs_is_blk_file(tfname) > 0) { + /* + * if the above test is true, then this is an Interix-type block device file: + */ + st->st_mode |= S_IFBLK; + st->st_rdev |= rdpfs_is_blk_file(tfname); + st->st_nlink = 1; + st->st_size = 0; + st->st_blocks = 0; + } + else if ((lst->files[idx]->FileAttributes & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM && rdpfs_is_chr_file(tfname) > 0) { + /* + * if the above test is true, then this is an Interix-type character device file: + */ + st->st_mode |= S_IFCHR; + st->st_rdev |= rdpfs_is_chr_file(tfname); + st->st_nlink = 1; + st->st_size = 0; + st->st_blocks = 0; + } + else if ((lst->files[idx]->FileAttributes & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM && lst->files[idx]->EndOfFile == 0) { + /* + * if the above test is true, then this is an Interix-type FIFO (named pipe): + */ + st->st_mode |= S_IFIFO; + st->st_nlink = 1; + st->st_size = 0; + st->st_blocks = 0; + } + else if ((lst->files[idx]->FileAttributes & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM && lst->files[idx]->EndOfFile == 1) { + /* + * if the above test is true, then this is an Interix-type socket: + */ + st->st_mode |= S_IFSOCK; + st->st_nlink = 1; + st->st_size = 0; + st->st_blocks = 0; + } + else if ((lst->files[idx]->FileAttributes & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM && lst->files[idx]->EndOfFile > 5 && lst->files[idx]->EndOfFile < 2048 && tfname != NULL && rdpfs_is_symlink(tfname) > 0) { + /* + * if the above test is true, then this is a "Minshall-French"-type symlink: + */ + st->st_mode |= S_IFLNK; + st->st_nlink = 1; + } + else { + /* set the "regular file" flag: */ + st->st_mode |= S_IFREG; + st->st_nlink = 1; + } + MDBGLOG("rdpfs","calling filler with name %s", lst->files[idx]->filename); + if (filler(buf, lst->files[idx]->filename, st, 0) != 0) { + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + return -ENOMEM; + } + } + if (lst->files[idx] != NULL) { + g_free(lst->files[idx]); + } + } + if (cbdata->IoStatus.Fields.Sev == STATUS_SEVERITY_ERROR) { + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + } + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + retstat = rdpfs_error("rdpfs_readdir lstat"); + MDBGLOG("rdpfs","ERROR [rdpfs_readdir()]: \"%s\" (retstat = %d)",nterr,retstat); + } + //log_fi(fi); + + if (cbdata->userdata != NULL) { + g_free(cbdata->userdata); + } + g_memset(cbdata,0,sizeof(callback)); + + if (empty_fi_fh > 0 && lfi != NULL && lfi->fh > -1) { + rdpfs_releasedir(path, lfi); + g_free(lfi); + } + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + return retstat; +} + +/** Release directory + * + * Introduced in version 2.3 + */ +static int rdpfs_releasedir(const char * path, struct fuse_file_info * fi) { + RDPFS_DECS; + int retstat = 0; + //tbus fd = -1; + char fpath[PATH_MAX]; + struct stream * s = NULL; + char buf[512]; + struct stat st; + //ptrdiff_t idx = 0; + //tbus objs[1] = { 0x00000000 }; + //size_t num_objs = 0; + //int timeout = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + ptrdiff_t size = 0x00000000; + struct _rdpfs_data rdata; + tbus fhandle = 0; + int uniqid = 0; + int reqid = -1; + callback * cbdata = NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + uint32_t crc32 = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *)&lmut,g_fs); + TC_MUTEX_LOCK(lmut); + TC_MUTEX_UNLOCK(mutex_fsop); + + MDBGLOG("rdpfs","\n\nrdpfs_releasedir(path=\"%s\")\n",path); + g_memset(&st,0,sizeof(struct stat)); + g_memset(fpath,0,sizeof(char)*PATH_MAX); + g_memset(buf,0,sizeof(char)*512); + g_memset(&rdata,0,sizeof(rdpfs_data)); + + rdpfs_fullpath(fpath, path); + + rdpfs_opcode = RDPFS_RELEASEDIR; + size = g_strlen(fpath) + 1; + fhandle = fi->fh; + uniqid = reqid; + + cbdata = (callback *)(&(g_reqids[reqid])); + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, size); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + if (size > 0) { + out_uint8a(s, fpath, size); + } + s_mark_end(s); + size = s->end - s->data; + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf(0, (void *)p, (size_t)(s->end - p)); + } + MDBGLOG("rdpfs"," ** rdpfs_releasedir(): sending [g_fd = %d]", g_fd); + trans_force_write(pcon); + MDBGLOG("rdpfs","sent."); + g_memset(s->data,0,MAX_STREAM); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + + MDBGLOG("rdpfs"," Waiting..."); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_WAIT(lcv,lmut); + MDBGLOG("rdpfs"," Done."); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + rdpfs_error("rdpfs_releasedir lstat"); + MDBGLOG("rdpfs","ERROR [rdpfs_releasedir()]: \"%s\" (retstat = %d)",nterr,retstat); + } + fi->fh = 0; + //log_fi(fi); + g_memset(cbdata,0,sizeof(callback)); + + MDBGLOG("rdpfs","rdpfs_releasedir(): done. ()"); + + TC_MUTEX_UNLOCK(lmut); + free_reqid_fs(reqid); + + return retstat; +} + +/** Synchronize directory contents + * + * If the datasync parameter is non-zero, then only the user data + * should be flushed, not the meta data + * + * Introduced in version 2.3 + */ +// when exactly is this called? when a user calls fsync and it +// happens to be a directory? ??? +int rdpfs_fsyncdir(const char *path, int datasync, struct fuse_file_info *fi) { + RDPFS_DECS; + int retstat = 0; + //tbus fhandle = 0; + //int uniqid = 0; + + MDBGLOG("rdpfs","\nrdpfs_fsyncdir(path=\"%s\", datasync=%d, fi=0x%08x)\n", path, datasync, fi); + //log_fi(fi); + + return retstat; +} + +/** + * Initialize filesystem + * + * The return value passes a pointer to the private_data field of + * fuse_context to all file operations and as a parameter to the + * destroy() method. + * + * Introduced in version 2.3 + * Changed in version 2.6 + * + * Undocumented but extraordinarily useful fact: the fuse_context is + * set up before this function is called, and + * fuse_get_context()->private_data returns the user_data passed to + * fuse_main(). Really seems like either it should be a third + * parameter coming in here, or else the fact should be documented + * (and this might as well return void, as it did in older versions of + * FUSE). + */ +void * rdpfs_init(struct fuse_conn_info * conn) { + RDPFS_DECS; + //tbus fd = -1; + int retstat = 0; + //char fpath[PATH_MAX]; + struct stream * s = NULL; + //char buf[512]; + //struct stat st; + //ptrdiff_t idx = 0; + //tbus objs[1] = { 0x00000000 }; + //size_t num_objs = 0; + //int timeout = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + ptrdiff_t size = 0x00000000; + tbus fhandle = 0; + int uniqid = 0; + uint32_t crc32 = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + + callback * cbdata = (callback *)NULL; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + int reqid = -1; + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + MDBGLOG("rdpfs","INFO\t[%s()]: called [%d, %d]", __func__, g_getpid(), g_gettid()); + + get_cv_fs(reqid, &lcv,g_fs); + rdpfs_opcode = RDPFS_INIT; + size = 0; + uniqid = reqid; + + if (g_fs != NULL) { + device_id = g_fs->device_id; + g_rdpfs = g_fs; + } + + MDBGLOG("rdpfs", "INFO\t[%s()]: device_id = %d; g_fs = %p [%d, %d]", __func__, device_id, g_fs, g_getpid(), g_gettid()); + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, size); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + s_mark_end(s); + size = s->end - s->data; + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf(0, (void *)p, (size_t)(s->end - p)); + } + + get_cbdata_fs(reqid, &cbdata); + cbdata->fs = g_fs; + cbdata->device_id = device_id; + cbdata->opcode = rdpfs_opcode; + pcon->callback_data = cbdata; + + + MDBGLOG("rdpfs","INFO\t[%s()]: sending (g_fd = %d, crc32 = 0x%8.8x, pcon = %p, pcon->sck = %d, lcv = %p, cbdata = %p) [%d, %d]", __func__, g_fd, *p_crc32, pcon, pcon->sck, lcv, cbdata, g_getpid(), g_gettid()); + if (cbdata != NULL) { + MDBGLOG("rdpfs","INFO\t[%s()]: (cbdata->magic = 0x%8.8x) [%d, %d]", __func__, cbdata->magic, g_getpid(), g_gettid()); + } + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + MDBGLOG("rdpfs", "INFO\t[%s()]: sent. [%d, %d]", __func__, g_getpid(), g_gettid()); + + MDBGLOG("rdpfs","INFO\t[%s()]: entering g_obj_wait loop: (lcv = %p, lmutex = %p) [%d, %d]",__func__,(void *)lcv,(void *)lmutex, g_getpid(), g_gettid()); + TC_COND_WAIT(lcv, lmutex); + MDBGLOG("rdpfs","INFO\t[%s()]: exiting g_obj_wait loop. [%d, %d]", __func__, g_getpid(), g_gettid()); + + MDBGLOG("rdpfs","INFO\t[%s()]: done. [%d, %d]", __func__, g_getpid(), g_gettid()); + + if (retstat < 0 || cbdata->IoStatus.Value >= STATUS_UNSUCCESSFUL) { + char * nterr = (char *)NULL; + if (cbdata->IoStatus.Value >= STATUS_UNSUCCESSFUL) { + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + nterr = ntstatus_string(cbdata->IoStatus.Value); + } + if (nterr != NULL) { + MDBGLOG("rdpfs","ERROR\t[%s()]: \"%s\" (retstat = %d) [%d, %d]",__func__,nterr,retstat, g_getpid(), g_gettid()); + } + else { + MDBGLOG("rdpfs","ERROR\t[%s()]: retstat = %d [%d, %d]",__func__,retstat, g_getpid(), g_gettid()); + } + } + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + MDBGLOG("rdpfs", "INFO\t[%s()]: done. [%d, %d]", __func__, g_getpid(), g_gettid()); + return RDPFS_DATA; +} + +/** + * Clean up filesystem + * + * Called on filesystem exit. + * + * Introduced in version 2.3 + */ +void rdpfs_destroy(void *userdata) { + MDBGLOG("rdpfs","\nrdpfs_destroy(userdata=0x%08x)\n", userdata); + + TC_MUTEX_DEINIT(mutex_fsop); + TC_COND_DEINIT(cv_readdir); +} + +/** + * Check file access permissions + * + * This will be called for the access() system call. If the + * 'default_permissions' mount option is given, this method is not + * called. + * + * This method is not called under Linux kernel versions 2.4.x + * + * Introduced in version 2.5 + */ +static int rdpfs_access(const char * path, int mask) { + RDPFS_DECS; + int retstat = 0; + //tbus fd = -1; + DIR * dp = (DIR *)NULL; + char fpath[PATH_MAX]; + struct stream * s = NULL; + char buf[512]; + struct stat st; + //ptrdiff_t idx = 0; + //tbus objs[1] = { 0x00000000 }; + //size_t num_objs = 0; + //int timeout = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + ptrdiff_t size = 0x00000000; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + struct fuse_file_info * lfi = NULL; + tc_p lmutex = (tc_p)NULL; + //tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + uint32_t crc32 = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + + MDBGLOG("rdpfs","\nrdpfs_access(path=\"%s\", mask=0%o)\n", path, mask); + + g_memset(&st,0,sizeof(struct stat)); + g_memset(fpath,0,sizeof(char)*PATH_MAX); + g_memset(buf,0,sizeof(char)*512); + + lfi = (struct fuse_file_info *)g_malloc(sizeof(struct fuse_file_info), 1); + dp = (DIR *)(uintptr_t) lfi->fh; + fhandle = (int)(uintptr_t)dp; + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *)&lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + rdpfs_opcode = RDPFS_ACCESS; + rdpfs_fullpath(fpath, path); + size = g_strlen(fpath) + 1; + uniqid = reqid; + + cbdata = &(g_reqids[reqid]); + cbdata->uniqid = uniqid; + cbdata->FileId = fhandle; + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, size); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + if (size > 0) { + out_uint8a(s, fpath, size); + } + s_mark_end(s); + size = s->end - s->data; + + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf(0, (void *)p, (size_t)(s->end - p)); + } + + MDBGLOG("rdpfs"," ** rdpfs_access(): sending [g_fd = %d; pcon->sck = %d; FileId = %d; uniqid = %d]", g_fd, pcon->sck, cbdata->FileId, cbdata->uniqid); + //trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + MDBGLOG("rdpfs","sent."); + + MDBGLOG("rdpfs","entering g_obj_wait loop:"); + //get_cv_fs(reqid,&lcv,g_fs); + //TC_COND_WAIT(lcv, lmutex); + MDBGLOG("rdpfs","g_obj_wait loop: exited."); + + if (lfi != NULL && lfi->fh > 0) { + rdpfs_release(path, lfi); + } + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + if (retstat < 0) { + retstat = rdpfs_error("rdpfs_access access"); + MDBGLOG("rdpfs","ERROR [rdpfs_access()]: unable to access file"); + } + + if (lfi != NULL) { + g_free(lfi); + } + + return retstat; +} + +/** + * Create and open a file + * + * If the file does not exist, first create it with the specified + * mode, and then open it. + * + * If this method is not implemented or under Linux kernel + * versions earlier than 2.6.15, the mknod() and open() methods + * will be called instead. + * + * Introduced in version 2.5 + */ +static int rdpfs_create(const char * path, mode_t mode, struct fuse_file_info * fi) { + RDPFS_DECS; + int retstat = 0; + //tbus fd = -1; + char fpath[PATH_MAX]; + struct stream * s = NULL; + char buf[512]; + struct stat st; + //ptrdiff_t idx = 0; + //tbus objs[1] = { 0x00000000 }; + //size_t num_objs = 0; + //int timeout = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + ptrdiff_t size = 0x00000000; + struct _rdpfs_data rdata; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + uint32_t pflags = 0x00000000; + uint32_t pshare = 0x00000000; + uint32_t poptions = 0x00000000; + uint32_t pattributes = 0x00000000; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + uint32_t crc32 = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + MDBGLOG("rdpfs","\n\nrdpfs_create(path=\"%s\")\n",path); + + g_memset(&st,0,sizeof(struct stat)); + g_memset(fpath,0,sizeof(char)*PATH_MAX); + g_memset(buf,0,sizeof(char)*512); + g_memset(&rdata,0,sizeof(rdpfs_data)); + + rdpfs_fullpath(fpath, path); + + get_cv_fs(reqid, &lcv,g_fs); + cbdata = &(g_reqids[reqid]); + + if ((fi->flags & O_ACCMODE) == O_RDONLY) { + pflags |= FILE_READ_DATA; + } + else if ((fi->flags & O_ACCMODE) == O_WRONLY) { + pflags |= (FILE_WRITE_DATA | FILE_APPEND_DATA); + } + else if ((fi->flags & O_ACCMODE) == O_RDWR) { + pflags |= (FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA); + } + else { + //pflags |= MAXIMUM_ALLOWED; + pflags |= (FILE_WRITE_DATA | FILE_APPEND_DATA); + } + + pflags |= (FILE_WRITE_DATA | FILE_APPEND_DATA); + pshare |= (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE); + poptions |= FILE_NON_DIRECTORY_FILE; + pattributes |= FILE_ATTRIBUTE_NORMAL; + + rdpfs_opcode = RDPFS_CREATE; + size = g_strlen(fpath) + 1; + uniqid = reqid; + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, size + 16); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + out_uint32_le(s, pflags); + out_uint32_le(s, pshare); + out_uint32_le(s, poptions); + out_uint32_le(s, pattributes); + if (size > 0) { + out_uint8a(s, fpath, size); + } + s_mark_end(s); + size = s->end - s->data; + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf(0, (void *)p, (size_t)(s->end - p)); + } + + MDBGLOG("rdpfs"," ** rdpfs_create(): sending [g_fd = %d]", g_fd); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + MDBGLOG("rdpfs","sent."); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + + MDBGLOG("rdpfs","entering g_obj_wait loop:"); + TC_COND_WAIT(lcv, lmutex); + MDBGLOG("rdpfs","exiting g_obj_wait loop."); + + fhandle = cbdata->FileId; + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("rdpfs","ERROR [rdpfs_create()]: \"%s\" (cbdata->IoStatus.Fields.Sev == STATUS_SEVERITY_ERROR)",nterr); + fhandle = -1; + } + else { + fi->fh = fhandle; + //log_fi(fi); + } + + MDBGLOG("rdpfs","rdpfs_create(): done. (fi->fh = %d; fhandle = %d; retstat = %d)",fi->fh,fhandle,retstat); + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + return retstat; +} + +static int rdpfs_create_args(const char * path, mode_t mode, struct fuse_file_info * fi, uint32_t pflags, uint32_t pshare, uint32_t poptions, uint32_t pattributes) { + RDPFS_DECS; + int retstat = 0; + //tbus fd = -1; + char fpath[PATH_MAX]; + struct stream * s = NULL; + char buf[512]; + struct stat st; + //ptrdiff_t idx = 0; + //tbus objs[1] = { 0x00000000 }; + //size_t num_objs = 0; + //int timeout = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + ptrdiff_t size = 0x00000000; + struct _rdpfs_data rdata; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + uint32_t crc32 = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + MDBGLOG("rdpfs","\n\nrdpfs_create_args(path=\"%s\"; mode = 0x%8.8x; pflags = 0x%8.8x; pshare = 0x%8.8x; poptions = 0x%8.8x; pattributes = 0x%8.8x)\n",path,mode,pflags,pshare,poptions,pattributes); + + g_memset(&st,0,sizeof(struct stat)); + g_memset(fpath,0,sizeof(char)*PATH_MAX); + g_memset(buf,0,sizeof(char)*512); + g_memset(&rdata,0,sizeof(rdpfs_data)); + + rdpfs_fullpath(fpath, path); + + get_cv_fs(reqid, &lcv,g_fs); + cbdata = &(g_reqids[reqid]); + + rdpfs_opcode = RDPFS_CREATE; + size = g_strlen(fpath) + 1; + uniqid = reqid; + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, size + 16); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + out_uint32_le(s, pflags); + out_uint32_le(s, pshare); + out_uint32_le(s, poptions); + out_uint32_le(s, pattributes); + if (size > 0) { + out_uint8a(s, fpath, size); + } + s_mark_end(s); + size = s->end - s->data; + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf(0, (void *)p, (size_t)(s->end - p)); + } + + MDBGLOG("rdpfs"," ** rdpfs_create_args(): sending [g_fd = %d]", g_fd); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + MDBGLOG("rdpfs","sent."); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + + MDBGLOG("rdpfs","entering g_obj_wait loop:"); + TC_COND_WAIT(lcv, lmutex); + MDBGLOG("rdpfs","exiting g_obj_wait loop."); + + fhandle = cbdata->FileId; + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("rdpfs","ERROR [rdpfs_create_args()]: \"%s\" (cbdata->IoStatus.Fields.Sev == STATUS_SEVERITY_ERROR)",nterr); + fhandle = -1; + } + else { + fi->fh = fhandle; + //log_fi(fi); + } + + MDBGLOG("rdpfs","rdpfs_create_args(): done. (fi->fh = %d; fhandle = %d; retstat = %d)",fi->fh,fhandle,retstat); + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + return retstat; +} + +/** + * Change the size of an open file + * + * This method is called instead of the truncate() method if the + * truncation was invoked from an ftruncate() system call. + * + * If this method is not implemented or under Linux kernel + * versions earlier than 2.6.15, the truncate() method will be + * called instead. + * + * Introduced in version 2.5 + */ +static int rdpfs_ftruncate(const char * path, off_t offset, struct fuse_file_info * fi) { + RDPFS_DECS; + //tbus fd = -1; + int retstat = 0; + char fpath[PATH_MAX] = ""; + struct stream * s = NULL; + //struct stat st; + //ptrdiff_t idx = 0; + //tbus objs[1] = { 0x00000000 }; + //size_t num_objs = 0; + ptrdiff_t fsize = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + //tbus empty_fi = 0; + struct fuse_file_info * lfi = NULL; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + uint64_t toffset = 0x0000000000000000; + uint32_t crc32 = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + MDBGLOG("rdpfs","\nrdpfs_ftruncate(path=\"%s\", offset=%lld, fi=0x%08x)\n", path, offset, fi); + + lfi = fi; + fhandle = lfi->fh; + toffset = offset; + + cbdata = &(g_reqids[reqid]); + rdpfs_fullpath(fpath,path); + rdpfs_opcode = RDPFS_FTRUNCATE; + fsize = g_strlen(fpath) + 1; + uniqid = reqid; + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, fsize + 8); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + out_uint64_le(s, toffset); + if (fsize > 0) { + out_uint8a(s, fpath, fsize); + } + s_mark_end(s); + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf(0, (void *)p, (size_t)(s->end - p)); + } + MDBGLOG("rdpfs"," ** rdpfs_ftruncate (about to send! fsize = %d; fpath = %s)", fsize, fpath); + fsize = s->end - s->data; + trans_force_write(pcon); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + MDBGLOG("rdpfs","sent."); + + MDBGLOG("rdpfs"," Entering wait loop..."); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_WAIT(lcv,lmutex); + MDBGLOG("rdpfs"," Finished."); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("rdpfs","ERROR [rdpfs_ftruncate()]: \"%s\" (cbdata->IoStatus.Value = 0x%8.8x; retstat = %d)", nterr, cbdata->IoStatus.Value, retstat); + } + g_memset(cbdata,0,sizeof(callback)); + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + return retstat; +} + +/** + * Get attributes from an open file + * + * This method is called instead of the getattr() method if the + * file information is available. + * + * Currently this is only called after the create() method if that + * is implemented (see above). Later it may be called for + * invocations of fstat() too. + * + * Introduced in version 2.5 + */ +// Since it's currently only called after rdpfs_create(), and rdpfs_create() +// opens the file, I ought to be able to just use the fd and ignore +// the path... +int rdpfs_fgetattr(const char *path, struct stat *statbuf, struct fuse_file_info *fi) { + RDPFS_DECS; + int retstat = 0; + //tbus fd = -1; + DIR * dp = (DIR *)NULL; + char fpath[PATH_MAX]; + struct stream * s = NULL; + char buf[512]; + struct stat st; + //ptrdiff_t idx = 0; + //tbus objs[1] = { 0x00000000 }; + //size_t num_objs = 0; + //int timeout = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + ptrdiff_t size = 0x00000000; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + struct fuse_file_info * lfi = NULL; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + filelist_entry * finfo = NULL; + uint32_t crc32 = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + + MDBGLOG("rdpfs","\n\nrdpfs_fgetattr(path=\"%s\", statbuf=0x%8.8x)\n",path,statbuf); + + g_memset(&st,0,sizeof(struct stat)); + g_memset(fpath,0,sizeof(char)*PATH_MAX); + g_memset(buf,0,sizeof(char)*512); + + lfi = fi; + dp = (DIR *)(uintptr_t) lfi->fh; + fhandle = (int)(uintptr_t)dp; + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *)&lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + rdpfs_opcode = RDPFS_FGETATTR; + rdpfs_fullpath(fpath, path); + size = g_strlen(fpath) + 1; + uniqid = reqid; + + cbdata = &(g_reqids[reqid]); + cbdata->userdata = (BYTE *)g_malloc(sizeof(filelist_entry), 1); + cbdata->uniqid = uniqid; + cbdata->FileId = fhandle; + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, size); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + if (size > 0) { + out_uint8a(s, fpath, size); + } + s_mark_end(s); + size = s->end - s->data; + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf(0, (void *)p, (size_t)(s->end - p)); + } + + MDBGLOG("rdpfs"," ** rdpfs_fgetattr(): sending [g_fd = %d; pcon->sck = %d; FileId = %d; uniqid = %d]", g_fd, pcon->sck, cbdata->FileId, cbdata->uniqid); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + MDBGLOG("rdpfs","sent."); + + MDBGLOG("rdpfs","entering g_obj_wait loop:"); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_WAIT(lcv, lmutex); + MDBGLOG("rdpfs","g_obj_wait loop: exited."); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("rdpfs","ERROR [rdpfs_fgetattr()]: \"%s\" (retstat = %d; cbdata->IoStatus.Value = 0x%8.8x)",nterr,retstat,cbdata->IoStatus.Value); + //g_free(nterr); + goto end; + } + + finfo = (filelist_entry *)(cbdata->userdata); + + g_memset(statbuf,0,sizeof(struct stat)); + statbuf->st_dev = 0x00000801; + statbuf->st_nlink = finfo->NumberOfLinks; + statbuf->st_ctime = FileTimeToUnix(finfo->CreationTime); + statbuf->st_mtime = FileTimeToUnix(finfo->LastWriteTime); + statbuf->st_atime = FileTimeToUnix(finfo->LastAccessTime); + statbuf->st_size = finfo->EndOfFile; + statbuf->st_blocks = finfo->AllocationSize; + statbuf->st_uid = 0; + statbuf->st_gid = 0; + if ((finfo->FileAttributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY) { + statbuf->st_mode = 0644; + } + else { + statbuf->st_mode = 0755; + } + if ((finfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY || finfo->Directory > 0) { + /* + * if the above test is true, then this is a directory: + */ + statbuf->st_mode |= S_IFDIR; + } + else if ((finfo->FileAttributes & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM && rdpfs_is_blk_file(fpath) > 0) { + /* + * if the above test is true, then this is an Interix-type block device file: + */ + statbuf->st_mode |= S_IFBLK; + statbuf->st_rdev |= rdpfs_is_blk_file(fpath); + statbuf->st_size = 0; + statbuf->st_blocks = 0; + } + else if ((finfo->FileAttributes & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM && rdpfs_is_chr_file(fpath) > 0) { + /* + * if the above test is true, then this is an Interix-type character device file: + */ + statbuf->st_mode |= S_IFCHR; + statbuf->st_rdev |= rdpfs_is_chr_file(fpath); + statbuf->st_size = 0; + statbuf->st_blocks = 0; + } + else if ((finfo->FileAttributes & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM && finfo->EndOfFile > 5 && finfo->EndOfFile < 2048 && rdpfs_is_symlink(fpath) > 0) { + /* + * if the above test is true, then this is a "Minshall-French"-type symlink: + */ + statbuf->st_mode |= S_IFLNK; + } + else if ((finfo->FileAttributes & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM && finfo->EndOfFile == 0) { + /* + * if the above test is true, then this is an Interix-type FIFO (named pipe): + */ + statbuf->st_mode |= S_IFIFO; + statbuf->st_size = 0; + statbuf->st_blocks = 0; + } + else if ((finfo->FileAttributes & FILE_ATTRIBUTE_SYSTEM) == FILE_ATTRIBUTE_SYSTEM && finfo->EndOfFile == 1) { + /* + * if the above test is true, then this is an Interix-type socket: + */ + statbuf->st_mode |= S_IFSOCK; + statbuf->st_size = 0; + statbuf->st_blocks = 0; + } + else { + statbuf->st_mode |= S_IFREG; + } + + end: + if (cbdata->userdata != NULL) { + g_free(cbdata->userdata); + } + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + return retstat; +} + +/** + * Ioctl + * + * flags will have FUSE_IOCTL_COMPAT set for 32bit ioctls in + * 64bit environment. The size and direction of data is + * determined by _IOC_*() decoding of cmd. For _IOC_NONE, + * data will be NULL, for _IOC_WRITE data is out area, for + * _IOC_READ in area and if both are set in/out area. In all + * non-NULL cases, the area is of _IOC_SIZE(cmd) bytes. + * + * Introduced in version 2.8 + */ +/* +int rdpfs_ioctl(const char * path, int cmd, void * arg, struct fuse_file_info * fi, unsigned int flags, void * data) { + RDPFS_DECS; + int retstat = 0; + tbus fd = -1; + char fpath[PATH_MAX]; + struct stream * s = NULL; + char buf[512]; + struct stat st; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + ptrdiff_t size = 0x00000000; + struct _rdpfs_data rdata; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + uint32_t crc32 = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + MDBGLOG("rdpfs","\n\nrdpfs_ioctl(path=\"%s\")\n",path); + + g_memset(&st,0,sizeof(struct stat)); + g_memset(fpath,0,sizeof(char)*PATH_MAX); + g_memset(buf,0,sizeof(char)*512); + g_memset(&rdata,0,sizeof(rdpfs_data)); + + rdpfs_fullpath(fpath, path); + + get_cv_fs(reqid, &lcv,g_fs); + cbdata = &(g_reqids[reqid]); + + rdpfs_opcode = RDPFS_IOCTL; + size = g_strlen(fpath) + 1; + uniqid = reqid; + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, size + 16); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + + out_uint32_le(s, cmd); + out_uint32_le(s, 0); + + if (size > 0) { + out_uint8a(s, fpath, size); + } + s_mark_end(s); + size = s->end - s->data; + + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf(0, (void *)p, (size_t)(s->end - p)); + } + + MDBGLOG("rdpfs"," ** rdpfs_ioctl(): sending [g_fd = %d]", g_fd); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + MDBGLOG("rdpfs","sent."); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + + MDBGLOG("rdpfs","entering g_obj_wait loop:"); + TC_COND_WAIT(lcv, lmutex); + MDBGLOG("rdpfs","exiting g_obj_wait loop."); + + fhandle = cbdata->FileId; + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("rdpfs","ERROR [rdpfs_ioctl()]: \"%s\" (cbdata->IoStatus.Fields.Sev == STATUS_SEVERITY_ERROR)",nterr); + fhandle = -1; + } + else { + fi->fh = fhandle; + //log_fi(fi); + } + + MDBGLOG("rdpfs","rdpfs_ioctl(): done."); + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + return retstat; +} +*/ + +static int rdpfs_fsctl(const char * path, struct fuse_file_info * fi, DWORD cmd, int length, void * data) { + RDPFS_DECS; + int retstat = 0; + //tbus fd = -1; + char fpath[PATH_MAX]; + struct stream * s = NULL; + char buf[512]; + struct stat st; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + ptrdiff_t size = 0x00000000; + struct _rdpfs_data rdata; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + FILE_OBJECTID_BUFFER object_id; + FILE_OBJECTID_BUFFER * oid = &object_id; + RETRIEVAL_POINTERS_BUFFER lrpn; + RETRIEVAL_POINTERS_BUFFER * rpn = &lrpn; + uint32_t crc32 = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + MDBGLOG("rdpfs","\n\nrdpfs_fsctl(path=\"%s\",cmd=\"0x%8.8x\",length=\"%d\")\n",path,cmd,length); + + g_memset(&lrpn,0,sizeof(RETRIEVAL_POINTERS_BUFFER)); + g_memset(&object_id,0,sizeof(FILE_OBJECTID_BUFFER)); + g_memset(&st,0,sizeof(struct stat)); + g_memset(fpath,0,sizeof(char)*PATH_MAX); + g_memset(buf,0,sizeof(char)*512); + g_memset(&rdata,0,sizeof(rdpfs_data)); + + rdpfs_fullpath(fpath, path); + + get_cv_fs(reqid, &lcv,g_fs); + cbdata = &(g_reqids[reqid]); + cbdata->userdata = (void *)oid; + + rdpfs_opcode = RDPFS_FSCTL; + size = g_strlen(fpath) + 1; + uniqid = reqid; + fhandle = fi->fh; + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, size + 8 + length); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + out_uint32_le(s, cmd); + out_uint32_le(s, length); + if (length > 0) { + out_uint8a(s, data, length); + } + if (size > 0) { + out_uint8a(s, fpath, size); + } + s_mark_end(s); + size = s->end - s->data; + + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf(0, (void *)p, (size_t)(s->end - p)); + } + + MDBGLOG("rdpfs"," ** rdpfs_fsctl(): sending [g_fd = %d]", g_fd); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + MDBGLOG("rdpfs","sent."); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + + MDBGLOG("rdpfs","entering g_obj_wait loop:"); + TC_COND_WAIT(lcv, lmutex); + MDBGLOG("rdpfs","exiting g_obj_wait loop."); + + fhandle = cbdata->FileId; + + if (data != NULL) { + if ((cmd == FSCTL_CREATE_OR_GET_OBJECT_ID || cmd == FSCTL_GET_OBJECT_ID) && oid != NULL) { + g_memcpy(data,oid,sizeof(FILE_OBJECTID_BUFFER)); + } + else if (cmd == FSCTL_GET_RETRIEVAL_POINTERS && rpn != NULL) { + g_memcpy(data,rpn,sizeof(RETRIEVAL_POINTERS_BUFFER)); + } + } + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("rdpfs","ERROR [rdpfs_fsctl()]: \"%s\" (cbdata->IoStatus.Fields.Sev == STATUS_SEVERITY_ERROR)",nterr); + fhandle = -1; + } + else { + fi->fh = fhandle; + } + + MDBGLOG("rdpfs","rdpfs_fsctl(): done."); + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + return retstat; +} + +/** + * Poll for IO readiness events + * + * Note: If ph is non-NULL, the client should notify + * when IO readiness events occur by calling + * fuse_notify_poll() with the specified ph. + * + * Regardless of the number of times poll with a non-NULL ph + * is received, single notification is enough to clear all. + * Notifying more times incurs overhead but doesn't harm + * correctness. + * + * The callee is responsible for destroying ph with + * fuse_pollhandle_destroy() when no longer in use. + * + * Introduced in version 2.8 + */ +int rdpfs_poll(const char * path, struct fuse_file_info * fi, struct fuse_pollhandle * ph, unsigned * reventsp) { + RDPFS_DECS; + int retstat = 0; + //tbus fd = -1; + char fpath[PATH_MAX]; + struct stream * s = NULL; + char buf[512]; + struct stat st; + struct trans * pcon = (struct trans *)NULL; + int rdpfs_opcode = 0x00000000; + ptrdiff_t size = 0x00000000; + struct _rdpfs_data rdata; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + int reqid = -1; + tbus fhandle = 0; + int uniqid = 0; + uint32_t crc32 = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + const uint32_t magic = RDP_PACKET_MAGIC; + char * p = (char *)NULL; + + TC_MUTEX_LOCK(mutex_fsop); + get_reqid_fs(&reqid); + get_mutex_fs(reqid,(tc_p *) &lmutex,g_fs); + TC_MUTEX_LOCK(lmutex); + TC_MUTEX_UNLOCK(mutex_fsop); + + MDBGLOG("rdpfs","\n\nrdpfs_poll(path=\"%s\")\n",path); + + g_memset(&st,0,sizeof(struct stat)); + g_memset(fpath,0,sizeof(char)*PATH_MAX); + g_memset(buf,0,sizeof(char)*512); + g_memset(&rdata,0,sizeof(rdpfs_data)); + + rdpfs_fullpath(fpath, path); + + get_cv_fs(reqid, &lcv,g_fs); + cbdata = &(g_reqids[reqid]); + + rdpfs_opcode = RDPFS_POLL; + size = g_strlen(fpath) + 1; + uniqid = reqid; + + TC_MUTEX_LOCK(mutex_pcon_fs); + pcon = g_fs->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpfs_opcode); + out_uint32_le(s, size + 16); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + if (size > 0) { + out_uint8a(s, fpath, size); + } + s_mark_end(s); + size = s->end - s->data; + + if (p_crc32 != NULL) { + *p_crc32 = Crc32_ComputeBuf(0, (void *)p, (size_t)(s->end - p)); + } + + MDBGLOG("rdpfs"," ** rdpfs_poll(): sending [g_fd = %d]", g_fd); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + MDBGLOG("rdpfs","sent."); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + + MDBGLOG("rdpfs","entering g_obj_wait loop:"); + TC_COND_WAIT(lcv, lmutex); + MDBGLOG("rdpfs","exiting g_obj_wait loop."); + + fhandle = cbdata->FileId; + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("rdpfs","ERROR [rdpfs_poll()]: \"%s\" (cbdata->IoStatus.Fields.Sev == STATUS_SEVERITY_ERROR)",nterr); + fhandle = -1; + } + else { + fi->fh = fhandle; + //log_fi(fi); + } + + MDBGLOG("rdpfs","rdpfs_poll(): done."); + + TC_MUTEX_UNLOCK(lmutex); + free_reqid_fs(reqid); + + return retstat; +} + +struct fuse_operations rdpfs_oper = { + //.flag_nullpath_ok = 1, + .init = rdpfs_init, + .getattr = rdpfs_getattr, + .fgetattr = rdpfs_fgetattr, + .mknod = rdpfs_mknod, + .mkdir = rdpfs_mkdir, + .unlink = rdpfs_unlink, + .rmdir = rdpfs_rmdir, + .rename = rdpfs_rename, + .truncate = rdpfs_truncate, + .ftruncate = rdpfs_ftruncate, + .utime = rdpfs_utime, + .open = rdpfs_open, + .read = rdpfs_read, + .write = rdpfs_write, + .statfs = rdpfs_statfs, + .release = rdpfs_release, + .opendir = rdpfs_opendir, + .readdir = rdpfs_readdir, + .releasedir = rdpfs_releasedir, + .destroy = rdpfs_destroy, + .access = rdpfs_access, + .create = rdpfs_create, +// .ioctl = rdpfs_ioctl, +// .poll = rdpfs_poll, +// .link = rdpfs_link, + .readlink = rdpfs_readlink, + .symlink = rdpfs_symlink, + .chmod = rdpfs_chmod, + .chown = rdpfs_chown, +// .flush = rdpfs_flush, +// .fsync = rdpfs_fsync, +// .fsyncdir = rdpfs_fsyncdir, +#if defined(__linux__) +// .listxattr = rdpfs_listxattr, + .getxattr = rdpfs_getxattr, +// .setxattr = rdpfs_setxattr, +// .removexattr = rdpfs_removexattr, +#endif +// .bmap = rdpfs_bmap, + .getdir = NULL +}; + +rdpfs * APP_CC rdpfs_main(int largc, char **iargv, char * mpath) { + rdpfs * rv = (rdpfs *)NULL; + ptrdiff_t i = 0; + struct rdpfs_state * rdpfs_data = (struct rdpfs_state *)NULL; + int compat = 26; + struct fuse * fuse = (struct fuse *)NULL; + char * mountpoint = (char *)NULL; + int multithreaded = 0; + tbus fd = -1; + struct fuse_chan * fc = (struct fuse_chan *)NULL; + struct fuse_operations * op = (struct fuse_operations *)NULL; + size_t op_size = 0; + char ** largv = (char **)NULL; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called [%d, %d]", __func__, g_getpid(), g_gettid()); + + largv = (char **)g_malloc(sizeof(char *) * largc, 1); + if (iargv != NULL) { + for (i = 0; i < largc; i++) { + if (iargv[i] != NULL) { + largv[i] = (char *)g_strdup(iargv[i]); + } + } + } + + rv = (rdpfs *)g_malloc(sizeof(rdpfs), 1); + if (rv == NULL) { + perror("main g_malloc(): failed to allocate rv as \"rdpfs\""); + abort(); + } + rdpfs_data = (struct rdpfs_state *)rv; + if (rdpfs_data == NULL) { + perror("main g_malloc(): failed to allocate rdpfs_data as \"struct rdpfs_state\""); + abort(); + } + + TC_MUTEX_INIT((tc_mut_t *)(&(rv->mut)),NULL); + TC_MUTEX_INIT((tc_mut_t *)(&(rv->mut_write)),NULL); + + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> about to lock mut>... [tid = %d; pid = %d]", __func__, g_gettid(), g_getpid()); + TC_MUTEX_LOCK(&(rv->mut)); + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> locked mut>. [tid = %d; pid = %d]", __func__, g_gettid(), g_getpid()); + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> about to lock mut_write>... [tid = %d; pid = %d]", __func__, g_gettid(), g_getpid()); + TC_MUTEX_LOCK(&(rv->mut_write)); + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> locked mut_write>. [tid = %d; pid = %d]", __func__, g_gettid(), g_getpid()); + + rv->magic = RDPFS_CONTEXT_MAGIC; + + // libfuse is able to do most of the command line parsing; all I + // need to do is to extract the rootdir; this will be the first + // non-option passed in. I'm using the GNU non-standard extension + // and having realpath malloc the space for the path + // the string. + for (i = 1; (i < largc) && (largv[i][0] == '-'); i++); + + if (mpath != NULL && g_strlen(mpath) > 0) { + rdpfs_data->rootdir = realpath(mpath, NULL); + mountpoint = mpath; + } + //multithreaded = 1; + + for (; i < largc; i++) { + largv[i] = largv[i+1]; + } + largc--; + + op = &rdpfs_oper; + op_size = sizeof(struct fuse_operations); + MDBGLOG("rdpfs","INFO\t[%s()]: largc = %d; largv[0] = %s; largv[1] = %s; op_size = %d; mountpoint = \"%s\".\t[%d, %d]",__func__,largc,largv[0],largv[1],op_size,mountpoint, g_getpid(), g_gettid()); + fuse = rdpfs_setup_common((largc+1), largv, op, op_size, &mountpoint, &multithreaded, (int *)(&fd), &fc, compat, (struct rdpfs_state *)rv); + if (fuse == NULL) { + fd = -1; + } + + rv->fuse = fuse; + rv->fd = fd; + rv->ch = fc; + if (mountpoint != NULL && g_strlen(mountpoint) > 0) { + rv->mountpoint = (char *)g_strdup(mountpoint); + } + + rv->initialized = 1; + + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> about to unlock mut_write>... [tid = %d; pid = %d]", __func__, g_gettid(), g_getpid()); + TC_MUTEX_UNLOCK(&(rv->mut_write)); + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> about to unlock mut>... [tid = %d; pid = %d]", __func__, g_gettid(), g_getpid()); + TC_MUTEX_UNLOCK(&(rv->mut)); + + MDBGLOG("rdpfs","INFO\t[%s()]: done. [%d, %d]",__func__, g_getpid(), g_gettid()); + + /* + * Return the file descriptor of the newly created + * fuse device, so that it can be monitored for incoming + * kernel communications (which should be handled + * appropriately): + */ + return rv; +} + + +/*****************************************************************************/ +static struct fuse *rdpfs_setup_common(int largc, char *largv[], + const struct fuse_operations *op, + size_t op_size, + char **mountpoint, + int *multithreaded, + int *fd, + struct fuse_chan **ifc, + int compat, + struct rdpfs_state * user_data) { + //struct fuse_args args = FUSE_ARGS_INIT(0, NULL); + //struct fuse_args args = FUSE_ARGS_INIT(largc, largv); + struct fuse_args args = FUSE_ARGS_INIT(3, NULL); + struct fuse * fuse = (struct fuse *)NULL; + struct fuse_chan * fc = (struct fuse_chan *)NULL; + int foreground = 0; + int res = 0; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called [%d, %d]", __func__, g_getpid(), g_gettid()); + + *mountpoint = "/media/tsclient"; + //res = fuse_parse_cmdline(&args, mountpoint, multithreaded, &foreground); + res = rdpfs_parse_cmdline(&args, mountpoint, multithreaded, &foreground); + //res = fuse_parse_cmdline(&args, mountpoint); + if (res == -1) { + return NULL; + } + + if (largv[0] != NULL && g_strlen(largv[0]) > 0) { + *mountpoint = largv[0]; + } + if (*mountpoint == NULL || g_strlen(*mountpoint) < 1) { + *mountpoint = "/media/tsclient"; + } + + MDBGLOG("rdpfs","INFO\t[%s()]: mountpoint = %s; largv[0] = %s; largv[1] = %s; pid = %d; tid = %d", __func__, *mountpoint, largv[0], largv[1], g_getpid(), g_gettid()); + + if (!g_directory_exist(*mountpoint)) { + g_dir_create(*mountpoint, 0777); + } + + MDBGLOG("rdpfs","INFO\t[%s()]: about to call fuse_mount()... [%d, %d]",__func__,g_getpid(),g_gettid()); + fc = fuse_mount(*mountpoint, &args); + MDBGLOG("rdpfs","INFO\t[%s()]: fuse_mount() called. [%d, %d]",__func__,g_getpid(),g_gettid()); + *ifc = fc; + + if (fc == NULL) { + MDBGLOG("rdpfs","ERROR\t[%s()]: failed to mount filesystem",__func__); + fuse_opt_free_args(&args); + goto err_free; + } + else { + MDBGLOG("rdpfs","INFO\t[%s()]: about to call fuse_chan_fd()... [%d, %d]",__func__,g_getpid(),g_gettid()); + *fd = fuse_chan_fd(fc); + MDBGLOG("rdpfs","INFO\t[%s()]: fuse_chan_fd() called. [%d, %d]",__func__,g_getpid(),g_gettid()); + } + if (*fd < 0) { + MDBGLOG("rdpfs","ERROR\t[%s()]: failed to obtain file descriptor [%d, %d]",__func__,g_getpid(),g_gettid()); + fuse_opt_free_args(&args); + goto err_free; + } + + MDBGLOG("rdpfs","INFO\t[%s()]: fd = %d [%d, %d]",__func__,*fd,g_getpid(),g_gettid()); + + fuse = fuse_new(fc, &args, op, op_size, user_data); + fuse_opt_free_args(&args); + if (fuse == NULL) { + MDBGLOG("rdpfs","ERROR\t[%s()]: \"fuse\" is a null pointer; unmounting... [%d, %d]",__func__, g_getpid(), g_gettid()); + goto err_unmount; + } + + res = fuse_set_signal_handlers(fuse_get_session(fuse)); + if (res == -1) { + MDBGLOG("rdpfs","ERROR\t[%s()]: fuse_set_signal_handlers() failed [%d, %d]",__func__, g_getpid(), g_gettid()); + goto err_destroy; + } + + MDBGLOG("rdpfs","INFO\t[%s()]: done. [%d, %d]",__func__, g_getpid(), g_gettid()); + + return fuse; + + err_destroy: + fuse_destroy(fuse); + err_unmount: + if (fc != NULL && *mountpoint != NULL) { + fuse_unmount(*mountpoint, fc); + } + err_free: + free(*mountpoint); + return NULL; +} + +static int fuse_helper_opt_proc(void *data, const char *arg, int key, struct fuse_args *outargs) { + struct helper_opts *hopts = data; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called", __func__); + + switch (key) { + case KEY_HELP: + //usage(outargs->argv[0]); + /* fall through */ + + case KEY_HELP_NOHEADER: + //helper_help(); + return fuse_opt_add_arg(outargs, "-h"); + + case KEY_VERSION: + //helper_version(); + return 1; + + case FUSE_OPT_KEY_NONOPT: + if (!hopts->mountpoint) + return fuse_opt_add_opt(&hopts->mountpoint, arg); + else { + fprintf(stderr, "fuse: invalid argument `%s'\n", arg); + return -1; + } + + default: + case KEY_KEEP: + return 1; + } +} + + +/*****************************************************************************/ +static int rdpfs_parse_cmdline(struct fuse_args * args, char ** mountpoint, int * multithreaded, int * foreground) { + int res = 0; + struct helper_opts hopts; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called", __func__); + + g_memset(&hopts, 0, sizeof(struct helper_opts)); + if (*mountpoint == NULL) { + *mountpoint = (char *)g_malloc(sizeof(char) * (g_strlen("/media/tsclient") + 1),1); + g_snprintf((char *)(*mountpoint),g_strlen("/media/test"),"%s","/media/tsclient"); + } + res = fuse_opt_parse(args, &hopts, fuse_helper_opts, fuse_helper_opt_proc); + if (res == -1) { + g_free(*mountpoint); + return -1; + } + + if (!hopts.fsname) { + if (res == -1) { + goto err; + } + } + if (mountpoint) { + *mountpoint = hopts.mountpoint; + } + else { + g_free(hopts.mountpoint); + } + + if (multithreaded) { + *multithreaded = !(hopts.singlethread); + } + if (foreground) { + *foreground = hopts.foreground; + } + return 0; + + err: + g_free(hopts.mountpoint); + return -1; +} + +/*****************************************************************************/ +inline unsigned long +rdpfs_hash(unsigned char *str) { + unsigned long hash = 5381; + int c = 0; + while ((c = (*str)++)) { + hash = ((hash << 5) + hash) + c; + } + return hash; +} + +/*****************************************************************************/ +static int APP_CC +rdpfs_cycle(rdpfs * self) { + int rv = 0; + int res = 0; + int done = 0; + struct fuse_session * se = (struct fuse_session *)NULL; + struct fuse_chan * ch = (struct fuse_chan *)NULL; + rdpfs * g_fs = (rdpfs *)NULL; + int g_fd = -1; + size_t bufsize = 0; + char buf[MAX_STREAM]; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called (self = %p)\t[%d, %d]", __func__, self, g_getpid(), g_gettid()); + + if (self == NULL) { + MDBGLOG("rdpfs","ERROR\t[%s()]: ** \"self\" is NULL ** [%d, %d]",__func__, g_getpid(), g_gettid()); + rv = -1; + goto end; + } + + //TC_MUTEX_LOCK(&(self->mut)); + + g_memset((char *)buf,0,sizeof(char)*MAX_STREAM); + g_fs = self; + g_fd = self->child_sck; + se = fuse_get_session(self->fuse); + ch = fuse_session_next_chan(se, NULL); + bufsize = fuse_chan_bufsize(ch); + if (buf == NULL) { + MDBGLOG("rdpfs","ERROR\t[%s()]: ** failed to allocate read buffer ** [%d, %d]",__func__, g_getpid(), g_gettid()); + rv = -1; + } + else { + while (done == 0) { + res = fuse_chan_recv(&ch, buf, bufsize); + if (res == -EINTR) { + continue; + } + else if (res >= 0) { + done = 1; + } + else if (res == -1) { + break; + } + else if (fuse_session_exited(se)) { + done = 2; + } + if (done == 1 && res > 0 && !(fuse_session_exited(se))) { + fuse_session_process(se, buf, res, ch); + } + } + if (fuse_session_exited(se)) { + fuse_session_reset(se); + sleep(200); + } + } + //TC_MUTEX_UNLOCK(&(self->mut)); + end:; + return rv; +} + + +rdpfs * APP_CC get_rdpfs_context(void) { + struct fuse_context * ltmp = (struct fuse_context *)NULL; + rdpfs * rv = (rdpfs *)NULL; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called [%d, %d]",__func__, g_getpid(), g_gettid()); + + //TC_MUTEX_LOCK(mutex_fuse); + ltmp = fuse_get_context(); + if (ltmp == NULL) { + //TC_MUTEX_UNLOCK(mutex_fuse); + MDBGLOG("rdpfs", "ERROR\t[%s()]: ltmp is NULL [%d, %d]", __func__, g_getpid(), g_gettid()); + return rv; + } + else { + MDBGLOG("rdpfs", "INFO\t[%s()]: ltmp = %p [%d, %d]", __func__, ltmp, g_getpid(), g_gettid()); + rv = (rdpfs *)(ltmp->private_data); + MDBGLOG("rdpfs", "INFO\t[%s()]: (...) [%d, %d]", __func__, g_getpid(), g_gettid()); + MDBGLOG("rdpfs", "INFO\t[%s()]: (rv = %p) [%d, %d]", __func__, rv, g_getpid(), g_gettid()); + MDBGLOG("rdpfs", "INFO\t[%s()]: (rv->magic = 0x%8.8x) [%d, %d]", __func__, rv->magic, g_getpid(), g_gettid()); + } + if (rv != NULL && rv->magic != RDPFS_CONTEXT_MAGIC) { + const uint32_t tmp = RDPFS_CONTEXT_MAGIC; + MDBGLOG("rdpfs", "ERROR\t[%s()]: bad magic (rv->magic is \"0x%8.8x\", but should be \"0x%8.8x\") [%d, %d]", __func__, rv->magic, tmp, g_getpid(), g_gettid()); + rv = (rdpfs *)NULL; + } + + MDBGLOG("rdpfs", "INFO\t[%s()]: done (rv = %p). [%d, %d]", __func__, rv, g_getpid(), g_gettid()); + //TC_MUTEX_UNLOCK(mutex_fuse); + return rv; +} + +rdpfs * APP_CC get_rdpfs_context_by_device_id(int device_id) { + rdpfs * rv = (rdpfs *)NULL; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called [%d, %d]", __func__, g_getpid(), g_gettid()); + + TC_MUTEX_LOCK(mutex_fuse); + rv = get_rdpfs_context(); + if (rv == NULL) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: rv is NULL [%d, %d]", __func__, g_getpid(), g_gettid()); + rv = (rdpfs *)NULL; + } + else if (rv != NULL && rv->magic != RDPFS_CONTEXT_MAGIC) { + const uint32_t tmp = RDPFS_CONTEXT_MAGIC; + MDBGLOG("rdpfs", "ERROR\t[%s()]: bad magic (rv->magic is \"0x%8.8x\", but should be \"0x%8.8x\") [%d, %d]", __func__, rv->magic, tmp, g_getpid(), g_gettid()); + rv = (rdpfs *)NULL; + } + else if (rv != NULL && rv->device_id != device_id) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: device_id does not match context (rv->device_id is \"0x%8.8x\", but should be \"0x%8.8x\") [%d, %d]", __func__, rv->device_id, device_id, g_getpid(), g_gettid()); + rv = (rdpfs *)NULL; + } + + MDBGLOG("rdpfs", "INFO\t[%s()]: done (rv = %p). [%d, %d]", __func__, rv, g_getpid(), g_gettid()); + TC_MUTEX_UNLOCK(mutex_fuse); + return rv; +} + +/*****************************************************************************/ +/***** child process-related section ******/ +/*****************************************************************************/ + + +/*****************************************************************************/ +static size_t APP_CC +parent_data_in(struct trans * trans) { + struct stream * s = (struct stream *)NULL; + int rdpfs_opcode = 0; + int rdpfs_reply = 0; + ptrdiff_t size = 0; + int error = 0; + int fault = 0; + tbus fhandle = 0; + int uniqid = 0; + unsigned char fdone = 0; + unsigned char fslocked = 0; + uint32_t device_id = 0; + uint32_t magic = 0; + uint32_t crc32 = 0; + uint32_t calc_crc32 = 0; + callback * cbdata = (callback *)NULL; + rdpfs * g_fs = (rdpfs *)NULL; + int tid = 0; + unsigned char initted = 0; + BYTE buf[MAX_STREAM]; + + tid = g_gettid(); + MDBGLOG("rdpfs", "INFO\t[%s()]: called [pid = %d; tid = %d]", __func__, g_getpid(), tid); + + g_memset((BYTE *)buf,0,sizeof(buf)); + if (trans == 0) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: trans is NULL [pid = %d; tid = %d]", __func__, g_getpid(), tid); + return 0; + } + + cbdata = (callback *)(trans->callback_data); + if (cbdata == NULL) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: cbdata is NULL [pid = %d; tid = %d]", __func__, g_getpid(), tid); + return 0; + } + else if (cbdata->magic != RDPFS_CB_MAGIC) { + const uint32_t tmp = RDPFS_CB_MAGIC; + MDBGLOG("rdpfs", "ERROR\t[%s()]: bad magic (cbdata->magic is 0x%8.8x, but should be 0x%8.8x) -- (g_rdpfs = %p; cbdata->fs = %p) [pid = %d; tid = %d]", __func__, cbdata->magic, tmp, g_rdpfs, cbdata->fs, g_getpid(), tid); + g_fs = g_rdpfs; + } + else { + g_fs = (rdpfs *)(cbdata->fs); + } + if (g_fs == NULL) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: g_fs is NULL [pid = %d; tid = %d]", __func__, g_getpid(), tid); + return 0; + } + + initted = g_fs->initialized; + if (initted) { + int tres = 0; + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> about to call TC_MUTEX_TRYLOCK(&(g_fs->mut_write))... [tid = %d; pid = %d]", __func__, tid, g_getpid()); + tres = TC_MUTEX_TRYLOCK(&(g_fs->mut_write)); + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> tres = %d [tid = %d; pid = %d]", __func__, tres, tid, g_getpid()); + if (tres != 0) { + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> about to lock mut>... [tid = %d; pid = %d]", __func__, tid, g_getpid()); + TC_MUTEX_LOCK(&(g_fs->mut_write)); + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> locked mut>... [tid = %d; pid = %d]", __func__, tid, g_getpid()); + } + } + + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> about to lock ... [pid = %d; tid = %d]", __func__, g_getpid(), tid); + TC_MUTEX_LOCK(mutex_pcon_fs); + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> locked . [pid = %d; tid = %d]", __func__, g_getpid(), tid); + s = (struct stream *)trans_get_in_s(trans); + in_uint32_le(s, magic); + in_uint32_le(s, rdpfs_reply); + in_uint32_le(s, size); + in_uint32_le(s, device_id); + in_uint32_le(s, fhandle); + in_uint32_le(s, uniqid); + in_uint32_le(s, crc32); + if (size > 0) { + error = trans_force_read(trans, size); + } + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> about to try to lock ... [pid = %d; tid = %d]", __func__, g_getpid(), tid); + fslocked = TC_MUTEX_TRYLOCK(mutex_fs_arr); + if (fslocked == 0) { + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> locked . [pid = %d; tid = %d]", __func__, g_getpid(), tid); + } + else { + MDBGLOG("rdpfs", "WARNING\t[%s()]: <<<>>> unable to lock . [pid = %d; tid = %d]", __func__, g_getpid(), tid); + } + if (g_fs == NULL && device_id > 0 && g_fs_arr != NULL) { + ptrdiff_t i = 0; + //for (i = 0; i < MAX_REQID; i++) { + for (i = 0; i < g_fs_count; i++) { + if (g_fs_arr[i] != NULL && g_fs_arr[i]->initialized > 0 && g_fs_arr[i]->device_id == device_id) { + g_fs = g_fs_arr[i]; + } + } + } + if (fslocked == 0) { + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> about to unlock ... [tid = %d; pid = %d]", __func__, tid, g_getpid()); + TC_MUTEX_UNLOCK(mutex_fs_arr); + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> unlocked . [tid = %d; pid = %d]", __func__, tid, g_getpid()); + } + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> about to unlock ... [tid = %d; pid = %d]", __func__, tid, g_getpid()); + TC_MUTEX_UNLOCK(mutex_pcon_fs); + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> unlocked . [tid = %d; pid = %d]", __func__, tid, g_getpid()); + if (error == 0) { + callback * g_reqids = (callback *)NULL; + if (size > 0) { + calc_crc32 = Crc32_ComputeBuf(0, s->p, size); + MDBGLOG("rdpfs", "INFO\t[%s()]: magic = 0x%8.8x, crc32 = 0x%8.8x, calc_crc32 = 0x%8.8x, g_fs = %p\t[%d, %d]", __func__, magic, crc32, calc_crc32, g_fs, g_getpid(), g_gettid()); + } + /* the entire message block has been read in, so process it: */ + fault = ((rdpfs_reply & RDPFS_ERROR) == RDPFS_ERROR) ? 1 : 0; + rdpfs_opcode = rdpfs_reply & (~(RDPFS_REPLY | RDPFS_ERROR)); + MDBGLOG("rdpfs","NOTE\t[%s()]: magic = 0x%8.8x; crc32 = 0x%8.8x; device_id = %d; g_fs->device_id = %d; rdpfs_opcode = 0x%8.8x; rdpfs_reply = 0x%8.8x; fault = %d; uniqid = %d\t[%d, %d]",__func__,magic,crc32,device_id,g_fs->device_id,rdpfs_opcode,rdpfs_reply,fault,uniqid, g_getpid(), g_gettid()); + + //g_fs = get_rdpfs_context_by_device_id(device_id); + if (g_fs == NULL) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: g_fs is NULL [tid = %d; pid = %d]", __func__, tid, g_getpid()); + return 0; + } + else { + g_reqids = (callback *)(g_fs->callbacks); + } + if (g_reqids == NULL) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: g_reqids[] is NULL [tid = %d; pid = %d]", __func__, tid, g_getpid()); + return 0; + } + + if (fault > 0) { + NTSTATUS iostatus = { .Value = 0x00000000 }; + int reqid = -1; + callback * cbdata = NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + char * nterr = (char *)NULL; + + MDBGLOG("rdpfs", "WARNING\t[%s()]: fault [tid = %d; pid = %d]", __func__, tid, g_getpid()); + + //TC_MUTEX_LOCK(mutex_fsop); + in_uint32_le(s, iostatus.Value); + + nterr = ntstatus_string(iostatus.Value); + MDBGLOG("rdpfs","WARNING\t[%s()]: --> FAULT: \"%s\" (status = 0x%8.8x) [tid = %d; pid = %d]",__func__,nterr,iostatus.Value, tid, g_getpid()); + if (g_reqids == NULL) { + return -1; + } + else { + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + if (reqid > -1) { + get_mutex_fs(reqid,(tc_p *)&lmut,g_fs); + //TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + cbdata->IoStatus.Value = iostatus.Value; + get_cv_fs(reqid, &lcv,g_fs); + TC_COND_SIGNAL(lcv); + } + else { + lmut = mutex_fsop; + } + } + //TC_MUTEX_UNLOCK(lmut); + } + else switch(rdpfs_opcode) { + case RDPFS_GETATTR: + case RDPFS_FGETATTR: + if (rdpfs_opcode == RDPFS_FGETATTR) { + MDBGLOG("rdpfs"," ^^ (RDPFS_FGETATTR)"); + } + else { + MDBGLOG("rdpfs"," ^^ (RDPFS_GETATTR)"); + } + { + DR_DRIVE_QUERY_INFORMATION_RSP iorsp; + int reqid = -1; + callback * cbdata = NULL; + filelist_entry * finfo = NULL; + tc_p lmut = (tbus)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + char * iptr = NULL; + char * optr = NULL; + ptrdiff_t inum = 0; + ptrdiff_t onum = 0; + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + construct_DR_DRIVE_QUERY_INFORMATION_RSP(&iorsp); + get_DR_DRIVE_QUERY_INFORMATION_RSP(&iorsp, s); + finfo = (filelist_entry *)cbdata->userdata; + finfo->CreationTime = iorsp.Buffer.all.BasicInformation.CreationTime; + finfo->LastAccessTime = iorsp.Buffer.all.BasicInformation.LastAccessTime; + finfo->LastWriteTime = iorsp.Buffer.all.BasicInformation.LastWriteTime; + finfo->ChangeTime = iorsp.Buffer.all.BasicInformation.ChangeTime; + finfo->FileAttributes = iorsp.Buffer.all.BasicInformation.FileAttributes; + finfo->EndOfFile = iorsp.Buffer.all.StandardInformation.EndOfFile; + finfo->AllocationSize = iorsp.Buffer.all.StandardInformation.AllocationSize; + finfo->NumberOfLinks = iorsp.Buffer.all.StandardInformation.NumberOfLinks; + finfo->Directory = iorsp.Buffer.all.StandardInformation.Directory; + finfo->DeletePending = iorsp.Buffer.all.StandardInformation.DeletePending; + iptr = (char *)iorsp.Buffer.all.NameInformation.FileName; + optr = finfo->filename; + inum = iorsp.Buffer.all.NameInformation.FileNameLength; + onum = sizeof(char) * 512; + g_instr(&optr, &onum, &iptr, &inum); + MDBGLOG("rdpfs"," --> Length = %d",iorsp.Length); + get_cv_fs(reqid, &lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + case RDPFS_MKNOD: + MDBGLOG("rdpfs"," ^^ (RDPFS_MKNOD)"); + { + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tbus)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + case RDPFS_MKDIR: + MDBGLOG("rdpfs"," ^^ (RDPFS_MKDIR)"); + { + int reqid = -1; + callback * cbdata = NULL; + DR_DRIVE_CREATE_RSP * iorsp = (DR_DRIVE_CREATE_RSP *)NULL; + tc_p lmut = (tbus)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + iorsp = (DR_DRIVE_CREATE_RSP *)(cbdata->userdata); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + construct_DR_DRIVE_CREATE_RSP(iorsp); + if (size > 0 && size < MAX_STREAM) { + get_DR_DRIVE_CREATE_RSP(iorsp, s); + } + cbdata->FileId = iorsp->DeviceCreateResponse.FileId; + MDBGLOG("rdpfs"," --> FileId = %d",cbdata->FileId); + get_cv_fs(reqid, &lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + case RDPFS_UNLINK: + MDBGLOG("rdpfs"," ^^ (RDPFS_UNLINK)"); + { + DR_DRIVE_SET_INFORMATION_RSP iorsp; + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + construct_DR_DRIVE_SET_INFORMATION_RSP(&iorsp); + get_DR_DRIVE_SET_INFORMATION_RSP(&iorsp, s); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + MDBGLOG("rdpfs"," ^^ (RDPFS_UNLINK): iorsp.Length = %d",iorsp.Length); + } + break; + case RDPFS_RMDIR: + MDBGLOG("rdpfs"," ^^ (RDPFS_RMDIR)"); + { + DR_DRIVE_SET_INFORMATION_RSP iorsp; + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + construct_DR_DRIVE_SET_INFORMATION_RSP(&iorsp); + get_DR_DRIVE_SET_INFORMATION_RSP(&iorsp, s); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + MDBGLOG("rdpfs"," ^^ (RDPFS_RMDIR): iorsp.Length = %d",iorsp.Length); + } + break; + case RDPFS_RENAME: + MDBGLOG("rdpfs"," ^^ (RDPFS_RENAME)"); + { + DR_DRIVE_SET_INFORMATION_RSP iorsp; + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + construct_DR_DRIVE_SET_INFORMATION_RSP(&iorsp); + get_DR_DRIVE_SET_INFORMATION_RSP(&iorsp, s); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + MDBGLOG("rdpfs"," ^^ (RDPFS_RENAME): iorsp.Length = %d",iorsp.Length); + } + break; + case RDPFS_LINK: + MDBGLOG("rdpfs"," ^^ (RDPFS_LINK)"); + { + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + case RDPFS_CHMOD: + MDBGLOG("rdpfs"," ^^ (RDPFS_CHMOD)"); + { + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + case RDPFS_CHOWN: + MDBGLOG("rdpfs"," ^^ (RDPFS_CHOWN)"); + { + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + case RDPFS_UTIME: + MDBGLOG("rdpfs"," ^^ (RDPFS_UTIME)"); + { + DR_DRIVE_SET_INFORMATION_RSP iorsp; + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + construct_DR_DRIVE_SET_INFORMATION_RSP(&iorsp); + get_DR_DRIVE_SET_INFORMATION_RSP(&iorsp, s); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + MDBGLOG("rdpfs"," ^^ (RDPFS_UTIME): iorsp.Length = %d",iorsp.Length); + } + break; + case RDPFS_OPENDIR: + MDBGLOG("rdpfs"," ^^ (RDPFS_OPENDIR)"); + { + DR_DRIVE_CREATE_RSP iorsp; + int reqid = -1; + callback * cbdata = NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + get_cv_fs(reqid, &lcv,g_fs); + construct_DR_DRIVE_CREATE_RSP(&iorsp); + if (size > 0 && size < MAX_STREAM) { + get_DR_DRIVE_CREATE_RSP(&iorsp, s); + } + cbdata->FileId = iorsp.DeviceCreateResponse.FileId; + MDBGLOG("rdpfs"," --> FileId = %d; fhandle = %d",cbdata->FileId,fhandle); + { + ptrdiff_t tsize = 0; + LOCAL_STREAM(v); + send_DR_DRIVE_CREATE_RSP(&iorsp, v); + s_mark_end(v); + tsize = v->end - v->data; + } + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + //case RDP_OPEN: + case RDPFS_OPEN: + MDBGLOG("rdpfs"," ^^ (RDPFS_OPEN)"); + { + DR_DRIVE_CREATE_RSP iorsp; + int reqid = -1; + callback * cbdata = NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + get_cv_fs(reqid, &lcv,g_fs); + construct_DR_DRIVE_CREATE_RSP(&iorsp); + if (size > 0 && size < MAX_STREAM) { + get_DR_DRIVE_CREATE_RSP(&iorsp, s); + } + cbdata->FileId = iorsp.DeviceCreateResponse.FileId; + MDBGLOG("rdpfs"," --> FileId = %d; fhandle = %d",cbdata->FileId,fhandle); + { + ptrdiff_t tsize = 0; + LOCAL_STREAM(v); + send_DR_DRIVE_CREATE_RSP(&iorsp, v); + s_mark_end(v); + tsize = v->end - v->data; + } + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + case RDPFS_READDIR: + MDBGLOG("rdpfs"," ^^ (RDPFS_READDIR)"); + { + filelist_entry ** files = (filelist_entry **)NULL; + int reqid = -1; + FILE_BOTH_DIR_INFORMATION dirinfo; + DR_DRIVE_QUERY_DIRECTORY_RSP lrsp; + DR_DRIVE_QUERY_DIRECTORY_RSP * rsp = &lrsp; + callback * cbdata = (callback *)NULL; + filelist * lst = (filelist *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + char * iptr = NULL; + char * optr = NULL; + ptrdiff_t inum = 0; + ptrdiff_t onum = 0; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + construct_DR_DRIVE_QUERY_DIRECTORY_RSP(rsp); + lst = (filelist *)(cbdata->userdata); + files = lst->files; + if (size > 0 && size < MAX_STREAM) { + get_DR_DRIVE_QUERY_DIRECTORY_RSP(rsp, s); + fdone = (rsp->DeviceIoReply.IoStatus.Value == STATUS_NO_MORE_FILES) ? 1 : 0; + if (fdone < 1) { + g_memcpy(&dirinfo,&(rsp->Buffer.both),sizeof(FILE_BOTH_DIR_INFORMATION)); + files[lst->count] = (filelist_entry *)g_malloc(sizeof(filelist_entry), 1); + iptr = (char *)dirinfo.FileName; + optr = (char *)files[lst->count]->filename; + inum = dirinfo.FileNameLength + 2; + onum = sizeof(char) * 512; + g_instr(&optr, &onum, &iptr, &inum); + files[lst->count]->index = lst->count; + files[lst->count]->FileAttributes = dirinfo.FileAttributes; + files[lst->count]->CreationTime = dirinfo.CreationTime; + files[lst->count]->LastAccessTime = dirinfo.LastAccessTime; + files[lst->count]->LastWriteTime = dirinfo.LastWriteTime; + files[lst->count]->ChangeTime = dirinfo.ChangeTime; + files[lst->count]->EndOfFile = dirinfo.EndOfFile; + files[lst->count]->AllocationSize = dirinfo.AllocationSize; + files[lst->count]->EaSize = dirinfo.EaSize; + lst->count++; + } + } + if (fdone > 0) { + get_cv_fs(reqid, &lcv,g_fs); + TC_COND_SIGNAL(lcv); + } + TC_MUTEX_UNLOCK(lmut); + } + break; + //case RDP_READ: + case RDPFS_READ: + MDBGLOG("rdpfs"," ^^ (RDPFS_READ)"); + { + DR_DRIVE_READ_RSP iorsp; + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + construct_DR_READ_RSP(&iorsp); + iorsp.ReadData = cbdata->userdata; + get_DR_READ_RSP(&iorsp, s); + cbdata->length = iorsp.Length; + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + MDBGLOG("rdpfs"," ^^ (RDPFS_READ): iorsp.Length = %d; iorsp.ReadData = \"%s\"",iorsp.Length,iorsp.ReadData); + } + break; + //case RDP_WRITE: + case RDPFS_WRITE: + MDBGLOG("rdpfs"," ^^ (RDPFS_WRITE)"); + { + DR_DRIVE_WRITE_RSP iorsp; + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + construct_DR_WRITE_RSP(&iorsp); + get_DR_WRITE_RSP(&iorsp, s); + cbdata->length = iorsp.Length; + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + case RDPFS_STATFS: + MDBGLOG("rdpfs"," ^^ (RDPFS_STATFS)"); + { + DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP iorsp; + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + construct_DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP(&iorsp); + get_DR_DRIVE_QUERY_VOLUME_INFORMATION_RSP(&iorsp, s); + cbdata->length = iorsp.Length; + g_memcpy(cbdata->userdata,iorsp.Buffer.bytes,iorsp.Length); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + case RDPFS_FSCTL: + MDBGLOG("rdpfs"," ^^ (RDPFS_FSCTL)"); + { + DR_CONTROL_RSP iorsp; + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + construct_DR_CONTROL_RSP(&iorsp); + iorsp.OutputBuffer = cbdata->userdata; + get_DR_CONTROL_RSP(&iorsp, s); + cbdata->length = iorsp.OutputBufferLength; + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + MDBGLOG("rdpfs"," ^^ (RDPFS_FSCTL): iorsp.OutputBufferLength = %d;",iorsp.OutputBufferLength); + } + break; + case RDPFS_FLUSH: + MDBGLOG("rdpfs"," ^^ (RDPFS_FLUSH)"); + { + DR_CONTROL_RSP iorsp; + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + construct_DR_CONTROL_RSP(&iorsp); + get_DR_CONTROL_RSP(&iorsp, s); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + MDBGLOG("rdpfs"," ^^ (RDPFS_FLUSH): done"); + } + break; + case RDPFS_RELEASE: + MDBGLOG("rdpfs"," ^^ (RDPFS_RELEASE)"); + { + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + case RDPFS_FSYNC: + MDBGLOG("rdpfs"," ^^ (RDPFS_FSYNC)"); + { + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + case RDPFS_RELEASEDIR: + MDBGLOG("rdpfs"," ^^ (RDPFS_RELEASEDIR)"); + { + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + case RDPFS_FSYNCDIR: + MDBGLOG("rdpfs"," ^^ (RDPFS_FSYNCDIR)"); + { + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + //case RDP_INIT: + case RDPFS_INIT: + MDBGLOG("rdpfs"," ^^ (RDPFS_INIT)"); + { + DR_DRIVE_CREATE_RSP iorsp; + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; +// cbdata = &(g_reqids[uniqid]); + cbdata = &(g_fs->callbacks[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + if (lmut == 0) { + MDBGLOG("rdpfs", "WARNING\t[%s()]: lmut is NULL (%p)!", __func__, lmut); + } + else { + TC_MUTEX_LOCK(lmut); + } + get_cv_fs(reqid, &lcv, g_fs); + g_memset(&iorsp,0,sizeof(DR_DRIVE_CREATE_RSP)); + construct_DR_DRIVE_CREATE_RSP(&iorsp); + if (size > 0 && size < MAX_STREAM) { + get_DR_DRIVE_CREATE_RSP(&iorsp, s); + } + if (trans != NULL && trans->callback_data == NULL) { + trans->callback_data = (rdpfs_data *)g_malloc(sizeof(rdpfs_data), 1); + } + if (trans != NULL) { + ((rdpfs_data *)(trans->callback_data))->FileId = iorsp.DeviceCreateResponse.FileId; + MDBGLOG("rdpfs"," --> FileId = %d",((rdpfs_data *)(trans->callback_data))->FileId); + } + TC_COND_SIGNAL(lcv); + if (lmut != 0) { + TC_MUTEX_UNLOCK(lmut); + } + } + break; + case RDPFS_ACCESS: + MDBGLOG("rdpfs"," ^^ (RDPFS_ACCESS)"); + { + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + case RDPFS_CREATE: + MDBGLOG("rdpfs"," ^^ (RDPFS_CREATE)"); + { + DR_DRIVE_CREATE_RSP iorsp; + int reqid = -1; + callback * cbdata = NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + get_cv_fs(reqid, &lcv,g_fs); + construct_DR_DRIVE_CREATE_RSP(&iorsp); + if (size > 0 && size < MAX_STREAM) { + get_DR_DRIVE_CREATE_RSP(&iorsp, s); + } + cbdata->FileId = iorsp.DeviceCreateResponse.FileId; + MDBGLOG("rdpfs"," --> FileId = %d; fhandle = %d",cbdata->FileId,fhandle); + { + ptrdiff_t tsize = 0; + LOCAL_STREAM(v); + send_DR_DRIVE_CREATE_RSP(&iorsp, v); + s_mark_end(v); + tsize = v->end - v->data; + } + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + case RDPFS_TRUNCATE: + case RDPFS_FTRUNCATE: + if (rdpfs_opcode == RDPFS_FTRUNCATE) { + MDBGLOG("rdpfs"," ^^ (RDPFS_FTRUNCATE)"); + } + else { + MDBGLOG("rdpfs"," ^^ (RDPFS_TRUNCATE)"); + } + { + DR_CONTROL_RSP iorsp; + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + + construct_DR_CONTROL_RSP(&iorsp); + get_DR_CONTROL_RSP(&iorsp, s); + + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + MDBGLOG("rdpfs"," ^^ (RDPFS_FTRUNCATE): done"); + } + break; + case RDPFS_GETXATTR: + MDBGLOG("rdpfs"," ^^ (RDPFS_GETXATTR)"); + { + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + case RDPFS_SETXATTR: + MDBGLOG("rdpfs"," ^^ (RDPFS_SETXATTR)"); + { + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + case RDPFS_LISTXATTR: + MDBGLOG("rdpfs"," ^^ (RDPFS_LISTXATTR)"); + { + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + case RDPFS_REMOVEXATTR: + MDBGLOG("rdpfs"," ^^ (RDPFS_REMOVEXATTR)"); + { + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + //TC_MUTEX_LOCK(mutex_fsop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex_fs(reqid,(tc_p *) &lmut,g_fs); + TC_MUTEX_LOCK(lmut); + //TC_MUTEX_UNLOCK(mutex_fsop); + get_cv_fs(reqid,&lcv,g_fs); + TC_COND_SIGNAL(lcv); + TC_MUTEX_UNLOCK(lmut); + } + break; + case RDPFS_DESTROY: + MDBGLOG("rdpfs"," ^^ (RDPFS_DESTROY)"); + exit(0); + break; + case RDPFS_END: + MDBGLOG("rdpfs"," ^^ (RDPFS_END)"); + exit(0); + break; + case RDPFS_ERROR: + MDBGLOG("rdpfs"," ^^ (RDPFS_ERROR)"); + exit(0); + break; + } + } + //TC_MUTEX_UNLOCK(mutex_pcon_fs); + if (initted) { + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> about to unlock mut_write>... [tid = %d; pid = %d]", __func__, tid, g_getpid()); + TC_MUTEX_UNLOCK(&(g_fs->mut_write)); + MDBGLOG("rdpfs", "INFO\t[%s()]: <<<>>> unlocked mut_write>... [tid = %d; pid = %d]", __func__, tid, g_getpid()); + } + MDBGLOG("rdpfs", "INFO\t[%s()]: done. [%d, %d]", __func__, g_getpid(), g_gettid()); + return error; +} + +typedef struct _handle_filesystem_loop_args { + rdpfs * fs; + struct trans * pcon; + tbus objs[2]; + int num_objs; + int timeout; + int check_parent; + int check_fuse; +} handle_filesystem_loop_args; + +static void * APP_CC +loop_parent_fs(void * inargs) { + void * rv = (void *)NULL; + handle_filesystem_loop_args * largs = (handle_filesystem_loop_args *)inargs; + struct trans * pcon = largs->pcon; + tbus * objs = (tbus *)(largs->objs); + size_t num_objs = largs->num_objs; + int timeout = largs->timeout; + int check_parent = largs->check_parent; + int tpid = 0; + tpid = g_gettid(); + MDBGLOG("rdpfs", "INFO\t[%s()]: spawned thread (inargs = %p)... [pid = %d, tid = %d]", __func__, inargs, g_getpid(), tpid); + if (inargs != NULL && objs != NULL && num_objs > 0 && check_parent > 0) { + MDBGLOG("rdpfs","INFO\t[%s()]: num_objs = %d, objs = %p",__func__,num_objs,objs); + /* handle any inbound communication from the parent process: */ + while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) { + if ((check_parent > 0) && g_is_wait_obj_set(objs[0])) { + TC_MUTEX_LOCK(mutex_parent_fs); + if (trans_check_wait_objs(pcon) != 0) { + MDBGLOG("rdpfs","ERROR [loop_parent_fs()]: "); + //rv = -1; + break; + } + TC_MUTEX_UNLOCK(mutex_parent_fs); + } + } + } + MDBGLOG("rdpfs", "INFO\t[%s()]: exiting thread (%d)", __func__, tpid); + TC_THREAD_EXIT(NULL); + return rv; +} + +static void * APP_CC +loop_fuse(void * inargs) { + void * rv = (void *)NULL; + handle_filesystem_loop_args * largs = (handle_filesystem_loop_args *)inargs; + rdpfs * fs = largs->fs; + tbus * objs = (tbus *)(largs->objs); + size_t num_objs = largs->num_objs; + int timeout = largs->timeout; + int check_fuse = largs->check_fuse; + int tpid = 0; + tpid = g_gettid(); + MDBGLOG("rdpfs", "INFO\t[%s()]: spawned thread (%d)...", __func__, tpid); + if (inargs != NULL && objs != NULL && num_objs > 0 && check_fuse > 0) { + /* handle communication from libfuse: */ + while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) { + if ((check_fuse > 0) && ((num_objs == 2 && g_is_wait_obj_set(objs[1])) || (num_objs == 1 && g_is_wait_obj_set(objs[0])))) { + TC_MUTEX_LOCK(mutex_fuse); + rdpfs_cycle(fs); + TC_MUTEX_UNLOCK(mutex_fuse); + } + } + } + MDBGLOG("rdpfs", "INFO\t[%s()]: exiting thread (%d)", __func__, tpid); + TC_THREAD_EXIT(NULL); + return rv; +} + +/*****************************************************************************/ +int APP_CC handle_filesystem(tbus sck, rdpfs * fs, rdpfs ** fs_arr, tc_p imut) { + int rv = 0; + struct trans * pcon = (struct trans *)NULL; + tbus objs[2] = { -1, -1 }; + size_t num_objs = 0; + int timeout = 0; + int check_parent = 0; + int check_fuse = 0; + handle_filesystem_loop_args largs; + tc_thread_t thread_parent; + tc_thread_t thread_fuse; + rdpfs * g_fs = (rdpfs *)NULL; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called (sck = %d) [%d, %d]", __func__, sck, g_getpid(), g_gettid()); + g_memset(&largs,0,sizeof(handle_filesystem_loop_args)); + g_memset(&thread_parent,0,sizeof(tbus)); + g_memset(&thread_fuse,0,sizeof(tbus)); + g_fs = fs; + g_fs_arr = fs_arr; + mutex_fs_arr = imut; + + mutex_pcon_fs = &(g_fs->g_mutex_pcon_fs); + mutex_fs = &(g_fs->g_mutex_fs); + mutex_fsop = &(g_fs->g_mutex_fsop); + mutex_parent_fs = &(g_fs->g_mutex_parent_fs); + mutex_fuse = &(g_fs->g_mutex_fuse); + mutex_reqid_fs = &(g_fs->g_mutex_reqid_fs); + mutex_getattr = &(g_fs->g_mutex_getattr); + cv_readdir = &(g_fs->g_cv_readdir); + + { + tc_t mattr; + tc_t cattr; + tc_p pmattr = (tc_p)&mattr; + tc_p pcattr = (tc_p)&cattr; + g_memset(pmattr,0,sizeof(tc_t)); + g_memset(pcattr,0,sizeof(tc_t)); + TC_MUTATTR_INIT(pmattr); + TC_MUTATTR_SETPSHARED(pmattr, TC_PROCESS_SHARED); + //TC_MUTATTR_SETPSHARED(pmattr, TC_PROCESS_PRIVATE); + TC_MUTATTR_SETTYPE(pmattr, TC_MUTEX_ERRORCHECK); + TC_MUTEX_INIT(mutex_pcon_fs,pmattr); + TC_MUTEX_INIT(mutex_fs,pmattr); + TC_MUTEX_INIT(mutex_fsop,pmattr); + TC_MUTEX_INIT(mutex_parent_fs,pmattr); + TC_MUTEX_INIT(mutex_fuse,pmattr); + TC_MUTEX_INIT(mutex_reqid_fs,pmattr); + TC_MUTEX_INIT(mutex_getattr,pmattr); + + TC_CONDATTR_INIT(pcattr); + TC_CONDATTR_SETPSHARED(pmattr, TC_PROCESS_SHARED); + //TC_CONDATTR_SETPSHARED(pmattr, TC_PROCESS_PRIVATE); + TC_COND_CREATE(cv_readdir,pcattr); + } + + TC_MUTEX_LOCK(mutex_pcon_fs); + TC_MUTEX_LOCK(mutex_fs); + + init_reqids_fs(fs); + + /* set up pcon as a transmission channel to the parent */ + + pcon = (struct trans *)trans_create((int)2, (int)MAX_STREAM, (int)MAX_STREAM); + + pcon->trans_data_in = &parent_data_in; + pcon->header_size = 28; +// pcon->header_size = 24; +// pcon->header_size = 16; + rv = trans_attach(pcon, sck); + + pcon->sck = sck; + //pcon->callback_data = fs; + fs->ccon = pcon; + + TC_MUTEX_UNLOCK(mutex_pcon_fs); + TC_MUTEX_UNLOCK(mutex_fs); + + g_memset(g_fattr_cache, 0, sizeof(g_fattr_cache)); + + if (rv > -1) { + + TC_MUTEX_LOCK(mutex_pcon_fs); + TC_MUTEX_LOCK(mutex_fs); + + /* add pcon to the set of monitored channels */ + if (pcon != NULL && pcon->sck > 0) { + objs[num_objs] = pcon->sck; + num_objs++; + check_parent = 1; + } + + /* add the appropriate /dev/fuse file descriptor to the set of monitored channels */ + if (fs->fd > 0) { + objs[num_objs] = fs->fd; + num_objs++; + check_fuse = 1; + } + + TC_MUTEX_UNLOCK(mutex_pcon_fs); + TC_MUTEX_UNLOCK(mutex_fs); + + /* monitor the above channels for input and respond appropriately */ + if (num_objs > 0 && objs[0] > -1) { + + TC_MUTEX_LOCK(mutex_pcon_fs); + TC_MUTEX_LOCK(mutex_fs); + + largs.fs = fs; + largs.pcon = pcon; + largs.objs[0] = objs[0]; + largs.objs[1] = objs[1]; + largs.num_objs = num_objs; + largs.timeout = timeout; + largs.check_parent = check_parent; + largs.check_fuse = check_fuse; + + TC_MUTEX_UNLOCK(mutex_pcon_fs); + TC_MUTEX_UNLOCK(mutex_fs); + + if (objs != NULL && num_objs > 0 && (check_parent > 0 || check_fuse > 0)) { + tc_t lattr; // (tc_threadattr_t)lattr + g_memset(&lattr,0,sizeof(tc_t)); + tc_threadattr_init(&lattr); + tc_threadattr_setdetachstate(&lattr, TC_CREATE_JOINABLE); + tc_thread_init_full(&thread_parent,(const tc_threadattr_t *)&lattr,&loop_parent_fs,&largs); + tc_thread_init_full(&thread_fuse,(const tc_threadattr_t *)&lattr,&loop_fuse,&largs); + + TC_THREAD_JOIN(thread_parent,NULL); + TC_THREAD_JOIN(thread_fuse,NULL); + } + } + } + + MDBGLOG("rdpfs","INFO\t[%s()]: done.",__func__); + return rv; +} + +static int APP_CC get_reqid_fs(int * inarg) { + int rv = 0; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called [%d, %d]", __func__, g_getpid(), g_gettid()); + + if (inarg == NULL) { + rv = -1; + } + else { + rdpfs * g_fs = (rdpfs *)NULL; + callback * g_reqids = (callback *)NULL; + + *inarg = -1; + + g_fs = get_rdpfs_context(); + MDBGLOG("rdpfs", "INFO\t[%s()]: g_fs = %p [%d, %d]", __func__, g_fs, g_getpid(), g_gettid()); + MDBGLOG("rdpfs", "INFO\t[%s()]: g_fs->device_id = %d [%d, %d]", __func__, g_fs->device_id, g_getpid(), g_gettid()); + if (g_fs == NULL) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: g_fs is NULL [%d, %d]", __func__, g_getpid(), g_gettid()); + return -1; + } + else { + g_reqids = (callback *)(g_fs->callbacks); + } + if (g_reqids == NULL) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: g_reqids[] is NULL [%d, %d]", __func__, g_getpid(), g_gettid()); + return -1; + } + + for (rv = 0; rv < MAX_REQID; rv++) { + MDBGLOG("rdpfs", "INFO\t[%s()]: (iteration %d) [%d, %d]", __func__, rv, g_getpid(), g_gettid()); + if (g_reqids[rv].opid == -1) { + tc_p tptr_cv; + tc_p tptr_mut; + *inarg = rv; + g_reqids[rv].opid = rv; + + g_reqids[rv].magic = RDPFS_CB_MAGIC; + g_reqids[rv].fs = g_fs; + g_reqids[rv].device_id = g_fs->device_id; + + tptr_cv = &(g_reqids[rv].cv); + tptr_mut = &(g_reqids[rv].mutex); + TC_MUTEX_INIT(tptr_mut,NULL); + TC_COND_CREATE(tptr_cv,NULL); + break; + } + } + } + MDBGLOG("rdpfs", "INFO\t[%s()]: done. [%d, %d]", __func__, g_getpid(), g_gettid()); + return rv; +} + +static int APP_CC free_reqid_fs(int inarg) { + int rv = 0; + rdpfs * g_fs = (rdpfs *)NULL; + callback * g_reqids = (callback *)NULL; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called [%d, %d]", __func__, g_getpid(), g_gettid()); + + g_fs = get_rdpfs_context(); + if (g_fs == NULL) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: g_fs is NULL [%d, %d]", __func__, g_getpid(), g_gettid()); + return -1; + } + else { + g_reqids = (callback *)(&(g_fs->callbacks)); + } + if (g_reqids == NULL) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: g_reqids[] is NULL [%d, %d]", __func__, g_getpid(), g_gettid()); + return -1; + } + + if (inarg < 0 || inarg > MAX_REQID) { + rv = -1; + } + else if (g_reqids[inarg].opid > -1 && g_reqids[inarg].opid <= MAX_REQID) { + TC_MUTEX_DEINIT(&(g_reqids[inarg].mutex)); + TC_COND_DEINIT(&(g_reqids[inarg].cv)); + g_memset(&(g_reqids[inarg]),0,sizeof(callback)); + g_reqids[inarg].opid = -1; + } + return rv; +} + + +static int APP_CC init_reqids_fs(rdpfs * g_fs) { + int rv = 0; + ptrdiff_t i = 0; + callback * g_reqids = (callback *)NULL; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called [%d, %d]", __func__, g_getpid(), g_gettid()); + + if (g_fs == NULL) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: g_fs is NULL [%d, %d]", __func__, g_getpid(), g_gettid()); + return -1; + } + else { + g_reqids = (callback *)(&(g_fs->callbacks)); + } + if (g_reqids == NULL) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: g_reqids[] is NULL [%d, %d]", __func__, g_getpid(), g_gettid()); + return -1; + } + + MDBGLOG("rdpfs", "INFO\t[%s()]: LOCKING [%d, %d]", __func__, g_getpid(), g_gettid()); + TC_MUTEX_LOCK(mutex_reqid_fs); + MDBGLOG("rdpfs", "INFO\t[%s()]: LOCKED [%d, %d]", __func__, g_getpid(), g_gettid()); + g_memset((callback *)g_reqids,0,sizeof(callback)*MAX_REQID); + for (i = 0; i < MAX_REQID; i++) { + tc_p tptr_mut; + tc_p tptr_cv; + g_reqids[i].opid = -1; + g_reqids[i].magic = RDPFS_CB_MAGIC; + g_reqids[i].fs = g_fs; + g_reqids[i].device_id = g_fs->device_id; + + tptr_cv = &(g_reqids[i].cv); + tptr_mut = &(g_reqids[i].mutex); + } + MDBGLOG("rdpfs", "INFO\t[%s()]: UNLOCKING [%d, %d]", __func__, g_getpid(), g_gettid()); + TC_MUTEX_UNLOCK(mutex_reqid_fs); + MDBGLOG("rdpfs", "INFO\t[%s()]: UNLOCKED [%d, %d]", __func__, g_getpid(), g_gettid()); + MDBGLOG("rdpfs","INFO\t[%s()]: done. [%d, %d]",__func__, g_getpid(), g_gettid()); + return rv; +} + +static int APP_CC get_mutex_fs(int reqid, tc_p * inarg, rdpfs * g_fs) { + int rv = 0; + callback * g_reqids = (callback *)NULL; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called [%d, %d]", __func__, g_getpid(), g_gettid()); + + if (g_fs == NULL) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: g_fs is NULL", __func__); + return -1; + } + else { + g_reqids = (callback *)(g_fs->callbacks); + } + if (g_reqids == NULL) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: g_reqids[] is NULL [%d, %d]", __func__, g_getpid(), g_gettid()); + return -1; + } + + if (reqid >= 0 && reqid < MAX_REQID) { + *inarg = (tc_p)(&(g_reqids[reqid].mutex)); + } + else { + rv = -1; + } + return rv; +} + +static int APP_CC get_cv_fs(int reqid, tc_p * inarg, rdpfs * g_fs) { + int rv = 0; + callback * g_reqids = (callback *)NULL; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called (reqid = %d) [%d, %d]", __func__, reqid, g_getpid(), g_gettid()); + + if (inarg == NULL) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: inarg is NULL [%d, %d]", __func__, g_getpid(), g_gettid()); + return -1; + } + + if (g_fs == NULL) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: g_fs is NULL [%d, %d]", __func__, g_getpid(), g_gettid()); + return -1; + } + else { + g_reqids = (callback *)(g_fs->callbacks); + } + if (g_reqids == NULL) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: g_reqids[] is NULL [%d, %d]", __func__, g_getpid(), g_gettid()); + return -1; + } + + if (reqid >= 0 && reqid < MAX_REQID) { + *inarg = (tc_p)(&(g_reqids[reqid].cv)); + } + else { + rv = -1; + } + MDBGLOG("rdpfs", "INFO\t[%s()]: done (rv = %d). [%d, %d]", __func__, rv, g_getpid(), g_gettid()); + return rv; +} + +static int APP_CC get_cbdata_fs(int reqid, callback ** inarg) { + int rv = 0; + rdpfs * g_fs = (rdpfs *)NULL; + callback * g_reqids = (callback *)NULL; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called [%d, %d]", __func__, g_getpid(), g_gettid()); + + if (inarg == NULL) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: inarg is NULL [%d, %d]", __func__, g_getpid(), g_gettid()); + return -1; + } + + g_fs = get_rdpfs_context(); + if (g_fs == NULL) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: g_fs is NULL [%d, %d]", __func__, g_getpid(), g_gettid()); + return -1; + } + else { + g_reqids = (callback *)(g_fs->callbacks); + } + if (g_reqids == NULL) { + MDBGLOG("rdpfs", "ERROR\t[%s()]: g_reqids[] is NULL [%d, %d]", __func__, g_getpid(), g_gettid()); + return -1; + } + else if (reqid >= 0 && reqid < MAX_REQID) { + *inarg = &(g_reqids[reqid]); + } + else { + rv = -1; + } + MDBGLOG("rdpfs", "INFO\t[%s()]: done (rv = %d). [%d, %d]", __func__, rv, g_getpid(), g_gettid()); + return rv; +} + + +static int APP_CC ntstatus_to_errcode(DWORD ntstat) { + int retstat = 0; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called", __func__); + + switch (ntstat) { + case 0: + retstat = 0; + break; + case STATUS_ACCESS_DENIED: + case STATUS_ACCESS_VIOLATION: + case STATUS_NETWORK_ACCESS_DENIED: + case STATUS_UNSUCCESSFUL: + retstat = -EACCES; + break; + case STATUS_GUARD_PAGE_VIOLATION: + case STATUS_INVALID_PARAMETER: + case STATUS_BAD_DEVICE_TYPE: + case STATUS_BAD_NETWORK_NAME: + case STATUS_INVALID_VOLUME_LABEL: + case STATUS_BAD_TOKEN_TYPE: + case STATUS_INVALID_GROUP_ATTRIBUTES: + case STATUS_BAD_MASTER_BOOT_RECORD: + case STATUS_INVALID_OPLOCK_PROTOCOL: + case STATUS_INVALID_INFO_CLASS: + case STATUS_INVALID_DEVICE_REQUEST: + case STATUS_INVALID_SYSTEM_SERVICE: + case STATUS_ILLEGAL_INSTRUCTION: + case STATUS_INVALID_LOCK_SEQUENCE: + case STATUS_INVALID_VIEW_SIZE: + case STATUS_INVALID_FILE_FOR_SECTION: + case STATUS_INVALID_DISPOSITION: + case STATUS_INVALID_UNWIND_TARGET: + case STATUS_INVALID_PORT_ATTRIBUTES: + case STATUS_INVALID_PARAMETER_MIX: + case STATUS_OBJECT_NAME_INVALID: + case STATUS_INVALID_VARIANT: + case STATUS_POWER_STATE_INVALID: + case STATUS_INVALID_DEVICE_OBJECT_PARAMETER: + case STATUS_INVALID_BLOCK_LENGTH: + retstat = -EINVAL; + break; +#ifdef ENOMEDIUM + case STATUS_NO_MEDIA_IN_DEVICE: + case STATUS_UNRECOGNIZED_MEDIA: + retstat = -ENOMEDIUM; + break; +#endif + case STATUS_SHARING_VIOLATION: + case STATUS_FILE_LOCK_CONFLICT: + case STATUS_LOCK_NOT_GRANTED: + case STATUS_SHARING_PAUSED: + case STATUS_SHARED_POLICY: + case STATUS_NOT_LOCKED: + case STATUS_PIPE_BUSY: + case STATUS_CONNECTION_IN_USE: + case STATUS_WAIT_FOR_OPLOCK: + retstat = -EBUSY; + break; + case STATUS_LOGON_FAILURE: + case STATUS_ACCOUNT_RESTRICTION: + case STATUS_ILL_FORMED_PASSWORD: + case STATUS_PASSWORD_RESTRICTION: + case STATUS_INVALID_LOGON_HOURS: + case STATUS_INVALID_WORKSTATION: + case STATUS_PASSWORD_EXPIRED: + case STATUS_ACCOUNT_DISABLED: + case STATUS_WRONG_PASSWORD: + case STATUS_SECTION_PROTECTION: + case STATUS_PRIVILEGE_NOT_HELD: + case STATUS_PRIVILEGED_INSTRUCTION: + case STATUS_PASSWORD_MUST_CHANGE: + case STATUS_ACCOUNT_LOCKED_OUT: + case STATUS_RESOURCE_NOT_OWNED: + case STATUS_LICENSE_VIOLATION: + case STATUS_LICENSE_QUOTA_EXCEEDED: + case STATUS_EVALUATION_EXPIRATION: + case STATUS_COPY_PROTECTION_FAILURE: + case STATUS_SMARTCARD_WRONG_PIN: + case STATUS_SMARTCARD_CARD_BLOCKED: + case STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED: + case STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT: + case STATUS_ACCESS_DISABLED_BY_POLICY_PATH: + case STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER: + case STATUS_ACCESS_DISABLED_BY_POLICY_OTHER: + case STATUS_CSS_AUTHENTICATION_FAILURE: + case STATUS_CSS_KEY_NOT_PRESENT: + case STATUS_CSS_KEY_NOT_ESTABLISHED: + case STATUS_INSUFFICIENT_LOGON_INFO: + retstat = -EPERM; + break; + case STATUS_DEVICE_DOES_NOT_EXIST: + case STATUS_DEVICE_NOT_CONNECTED: + case STATUS_DEVICE_POWER_FAILURE: + case STATUS_DEVICE_REMOVED: + case STATUS_PLUGPLAY_NO_DEVICE: + case STATUS_VOLUME_DISMOUNTED: + case STATUS_NOINTERFACE: + case STATUS_PARTITION_FAILURE: + retstat = -ENODEV; + break; + case STATUS_NO_MORE_FILES: + case STATUS_OBJECT_NAME_NOT_FOUND: + case STATUS_NOT_FOUND: + case STATUS_INVALID_PLUGPLAY_DEVICE_PATH: + case STATUS_NO_SUCH_FILE: + case STATUS_NETWORK_NAME_DELETED: + case STATUS_FILE_IS_OFFLINE: + case STATUS_MOUNT_POINT_NOT_RESOLVED: + retstat = -ENOENT; + break; + case STATUS_LOGON_SESSION_EXISTS: + case STATUS_DUPLICATE_NAME: + case STATUS_ALIAS_EXISTS: + case STATUS_ADDRESS_ALREADY_EXISTS: + case STATUS_DUPLICATE_OBJECTID: + case STATUS_OBJECTID_EXISTS: + retstat = -EEXIST; + break; + case STATUS_WRONG_VOLUME: + retstat = -EXDEV; + break; + case STATUS_BUFFER_TOO_SMALL: + case STATUS_SECTION_TOO_BIG: + case STATUS_SYSTEM_HIVE_TOO_LARGE: + retstat = -E2BIG; + break; + case STATUS_MEMORY_NOT_ALLOCATED: + case STATUS_NO_MEMORY: + case STATUS_INSUFFICIENT_RESOURCES: + case STATUS_INSUFF_SERVER_RESOURCES: + retstat = -ENOMEM; + break; + case STATUS_INVALID_HANDLE: + case STATUS_FILE_INVALID: + case STATUS_INVALID_PORT_HANDLE: + case STATUS_FILE_DELETED: + case STATUS_FILE_CLOSED: + case STATUS_FILE_CORRUPT_ERROR: + case STATUS_USER_MAPPED_FILE: + case STATUS_NOT_A_REPARSE_POINT: + case STATUS_DIRECTORY_IS_A_REPARSE_POINT: + case STATUS_FILE_NOT_ENCRYPTED: + case STATUS_FILE_ENCRYPTED: + case STATUS_CORRUPT_SYSTEM_FILE: + case STATUS_HANDLE_NOT_CLOSABLE: + retstat = -EBADF; + break; + case STATUS_FILES_OPEN: + retstat = -EMFILE; + break; + case STATUS_TOO_MANY_OPENED_FILES: + retstat = -ENFILE; + break; + case STATUS_PIPE_NOT_AVAILABLE: + case STATUS_INVALID_PIPE_STATE: + case STATUS_PIPE_BROKEN: + case STATUS_PIPE_EMPTY: + retstat = -EPIPE; + break; + case STATUS_DISK_FULL: + case STATUS_NO_LOG_SPACE: + case STATUS_LOG_FILE_FULL: + case STATUS_NO_SPOOL_SPACE: + case STATUS_PRINT_QUEUE_FULL: + case STATUS_DESTINATION_ELEMENT_FULL: + retstat = -ENOSPC; + break; + case STATUS_MEDIA_WRITE_PROTECTED: + retstat = -EROFS; + break; + case STATUS_DIRECTORY_NOT_EMPTY: + retstat = -ENOTEMPTY; + break; + case STATUS_RETRY: + retstat = -EAGAIN; + break; + case STATUS_OBJECT_PATH_NOT_FOUND: + case STATUS_NOT_A_DIRECTORY: + retstat = -ENOTDIR; + break; + case STATUS_FILE_IS_A_DIRECTORY: + retstat = -EISDIR; + break; + case STATUS_UNEXPECTED_IO_ERROR: + case STATUS_IO_PRIVILEGE_FAILED: + case STATUS_DEVICE_NOT_READY: + case STATUS_IO_DEVICE_ERROR: + case STATUS_OPEN_FAILED: + case STATUS_REPLY_MESSAGE_MISMATCH: + case STATUS_LOST_WRITEBEHIND_DATA: + retstat = -EIO; + break; + case STATUS_NOT_SUPPORTED: + case STATUS_ILLEGAL_FUNCTION: + case STATUS_WMI_NOT_SUPPORTED: + retstat = -EOPNOTSUPP; + break; + case STATUS_PIPE_DISCONNECTED: + case STATUS_CONNECTION_ABORTED: + case STATUS_CONNECTION_DISCONNECTED: + case STATUS_CONNECTION_RESET: + retstat = -ECONNRESET; + break; + default: + break; + } + + return retstat; +} + +/** + * rdpfs_parse_path - split path to path and stream name. + * @org_path: path to split + * @path: pointer to buffer in which parsed path saved + * @stream_name: pointer to buffer where stream name in unicode saved + * + * This function allocates buffers for @*path and @*stream, user must free them + * after use. + * + * Return values: + * <0 Error occurred, return -errno; + * 0 No stream name, @*stream is not allocated and set to AT_UNNAMED. + * >0 Stream name length in unicode characters. + */ +static APP_CC +ptrdiff_t rdpfs_parse_path(const char *org_path, char **path, char **stream_name) { + char * tmp_stream_name = (char *)NULL; + ptrdiff_t res = 0; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called", __func__); + + tmp_stream_name = (char *)g_strdup(org_path); + if (!tmp_stream_name) { + res = -1; + } + else { + *path = (char *)g_strsep(&tmp_stream_name, ":"); + if (tmp_stream_name != NULL) { + *stream_name = (char *)g_strdup(tmp_stream_name); + res = g_strlen(*stream_name); + } + } + + return res; +} + +/****/ + +static int APP_CC input_MINSHALL_FRENCH_SYMLINK(MINSHALL_FRENCH_SYMLINK * self, struct stream * s) { + int rv = 0; + int ml = 0; + int sl = 0; + int tl = 0; + char * tpos = (char *)NULL; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called", __func__); + + if (s != NULL && s->p != NULL && s->end != NULL && (s->end - s->p) > 4) { + tpos = s->p; + } + else { + tpos = NULL; + } + if (tpos == NULL || tpos[0] != 'X' || tpos[1] != 'S' || tpos[2] != 'y' || tpos[3] != 'm' || tpos[4] != '\n') { + rv = -1; + } + else { + in_uint8a(s, self->XSym, 4); + in_uint8s(s, 1); + tpos = s->p; + while (*tpos != '\n' && tpos < s->end && tl < 6) { + tl++; + tpos++; + } + if (tl == 0) { + rv = -1; + goto end; + } + in_uint8a(s, self->len, tl); + in_uint8s(s, 1); + tpos = s->p; + while (*tpos != '\n' && tpos < s->end && ml < 33) { + ml++; + tpos++; + } + if (ml == 0) { + rv = -1; + goto end; + } + in_uint8a(s, self->md5sum, ml); + in_uint8s(s, 1); + tpos = s->p; + while (*tpos != '\n' && tpos < s->end && sl < 1024) { + sl++; + tpos++; + } + if (sl == 0) { + rv = -1; + goto end; + } + in_uint8a(s, self->target, sl); + in_uint8s(s, 1); + rv = (4 + 1) + (tl + 1) + (ml + 1) + (sl + 1); + } + end:; + return rv; +} + +static int APP_CC send_MINSHALL_FRENCH_SYMLINK(MINSHALL_FRENCH_SYMLINK * self, struct stream * s) { + int rv = 0; + int ml = 0; + int sl = 0; + int tl = 0; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called", __func__); + + if (self == NULL || s == NULL || self->len == NULL || self->md5sum == NULL || self->target == NULL || self->len[0] == '\0' || self->md5sum[0] == '\0' || self->target[0] == '\0' || self->XSym[0] != 'X' || self->XSym[1] != 'S' || self->XSym[2] != 'y' || self->XSym[3] != 'm') { + rv = -1; + } + else { + //tl = g_strlen(self->len); + tl = 5; + sl = g_atoi(self->len); + ml = 32; + } + if (ml < 1 || tl < 1 || sl < 1 || tl > 5 || sl > 1024 || ml > 32) { + rv = -1; + } + if (rv > -1) { + out_uint8a(s, self->XSym, 4); + out_uint8(s, '\n'); + out_uint8a(s, self->len, tl); + out_uint8(s, '\n'); + out_uint8a(s, self->md5sum, ml); + out_uint8(s, '\n'); + out_uint8a(s, self->target, sl); + out_uint8(s, '\n'); + rv = (4 + 1) + (tl + 1) + (ml + 1) + (sl + 1); + } + return rv; +} + +static char * APP_CC get_MINSHALL_FRENCH_SYMLINK(MINSHALL_FRENCH_SYMLINK * self) { + char * rv = (char *)NULL; + ptrdiff_t sl = 0; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called", __func__); + + if (self != NULL && self->target != NULL && self->len != NULL) { + sl = g_atoi(self->len); + if (sl > 0) { + rv = (char *)g_malloc(sizeof(char) * (sl + 1), 1); + g_memcpy(rv,self->target,sl); + } + } + return rv; +} + +static int APP_CC set_MINSHALL_FRENCH_SYMLINK(MINSHALL_FRENCH_SYMLINK * self, const char * val) { + int rv = 0; + ptrdiff_t sl = 0; + uint32_t state[4] = {0, 0, 0, 0}; + MD5_CTX lmd5; + MD5_CTX * md5 = &lmd5; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called", __func__); + + if (self != NULL && val != NULL && g_strlen(val) > 0) { + sl = g_strlen(val); + if (sl > 0) { + g_memset(md5,0,sizeof(MD5_CTX)); + MD5Init(md5); + MD5Update(md5, (unsigned char *)val, sl); + MD5Final((unsigned char *)state, md5); + g_snprintf(self->len,6,"%5.5d",sl); + g_snprintf(self->md5sum,33,"%08x%08x%08x%08x", htobel(state[0]), htobel(state[1]), htobel(state[2]), htobel(state[3])); + g_snprintf(self->target,MIN((sl + 1),1024),"%s",val); + } + else { + rv = -1; + } + } + else { + rv = -1; + } + return rv; +} + +static int APP_CC construct_MINSHALL_FRENCH_SYMLINK(MINSHALL_FRENCH_SYMLINK * self) { + int rv = 0; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called", __func__); + + if (self == NULL) { + rv = -1; + } + else { + g_memset(self,0,sizeof(MINSHALL_FRENCH_SYMLINK)); + self->XSym[0] = 'X'; + self->XSym[1] = 'S'; + self->XSym[2] = 'y'; + self->XSym[3] = 'm'; + self->in = &input_MINSHALL_FRENCH_SYMLINK; + self->out = &send_MINSHALL_FRENCH_SYMLINK; + self->get = &get_MINSHALL_FRENCH_SYMLINK; + self->set = &set_MINSHALL_FRENCH_SYMLINK; + } + return rv; +} + +static int APP_CC send_INTERIX_DEV_FILE(INTERIX_DEV_FILE * self, struct stream * s) { + int rv = 0; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called", __func__); + + if (self == NULL || s == NULL || self->magic == NULL || self->magic[0] != 'I' || self->magic[1] != 'n' || self->magic[2] != 't' || self->magic[3] != 'x' || !((self->magic[4] == 'B' && self->magic[5] == 'L' && self->magic[6] == 'K') || (self->magic[4] == 'C' && self->magic[5] == 'H' && self->magic[6] == 'R')) || self->magic[7] != '\0') { + rv = -1; + } + else { + char * m = self->magic; + out_uint8a(s, m, 8); + out_uint64_le(s, self->major); + out_uint64_le(s, self->minor); + } + + return rv; +} + + +static int APP_CC set_INTERIX_DEV_FILE(INTERIX_DEV_FILE * self, const char dtype, int64_t dev_maj, int64_t dev_min) { + int rv = 0; + const char bdev[8] = {'I','n','t','x','B','L','K','\0'}; + const char cdev[8] = {'I','n','t','x','C','H','R','\0'}; + char * dmagic = (char *)NULL; + char tc = '\0'; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called", __func__); + + if (self == NULL) { + rv = -1; + goto end_tag; + } + tc = (dtype == 'C' || dtype =='c') ? 'c' : (dtype == 'B' || dtype == 'b') ? 'b' : '\0'; + if (tc == 'b') { + dmagic = (char *)bdev; + } + else if (tc == 'c') { + dmagic = (char *)cdev; + } + if (dmagic == NULL) { + rv = -1; + goto end_tag; + } + g_memcpy(self->magic,dmagic,8); + self->major = dev_maj; + self->minor = dev_min; + + end_tag: + return rv; +} + +static int APP_CC construct_INTERIX_DEV_FILE(INTERIX_DEV_FILE * self) { + int rv = 0; + + MDBGLOG("rdpfs", "INFO\t[%s()]: called", __func__); + + if (self == NULL) { + rv = -1; + } + else { + g_memset(self,0,sizeof(INTERIX_DEV_FILE)); + } + + return rv; +} + diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/rdpport.c posixrdp/posixxrdp.orig/sesman/chansrv/rdpport.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/rdpport.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/rdpport.c 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,2496 @@ +/* + * + * Serial port and/or parallel port redirection over RDP + * + */ + +#include "params.h" + +#if defined(__linux__) +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +#include "log.h" +#include "arch.h" +#include "parse.h" +#include "defines.h" +#include "rdpdr.h" +#include "rdpdr_methods.h" +#include "rdpport_defs.h" +#include "trans.h" +#include "devredir_defs.h" +#include "global.h" +#include "ntddser.h" +#include "crc32.h" +#include "thread_calls.h" +#include "thread_macros.h" +#include "dbg.h" + +#define CN_TEST_IDX CN_IDX_RDPUART +#define CN_TEST_VAL CN_VAL_RDPUART + +static int g_read_outstanding = 0; +static int g_keep_going = 1; +static int g_stop = 0; +static int g_fd = -1; +static int g_fhandle = -1; +static rdpport_t * g_port = (rdpport_t *)NULL; + +static uint32_t seq = 0; + +#ifndef MAX_REQID +#define MAX_REQID 25 +#endif + +static int g_irq_idx = -1; +static callback * g_irq_cb = (callback *)NULL; +static callback g_reqids[MAX_REQID]; +static void * rdp_addport(void *); +static void * rdp_irq_callback(void *); + +#ifndef MAX_MUTEX +#define MAX_MUTEX 25 +#endif + +typedef struct thread_head { +// pthread_t * thread; + tc_t * thread; + struct thread_head * next; + struct thread_head * prev; +} thread_head_t; + +static thread_head_t * g_thread_list = (thread_head_t *)NULL; + +extern tc_t g_mutex; +extern tc_p mut; + +//static tc_t mutex_device_port; +static tc_t g_mutex_pcon_port; +static tc_t g_mutex_port; +static tc_t g_mutex_device_port; +static tc_t g_mutex_parent; +static tc_t g_mutex_portop; +static tc_t g_mutex_reqid; +static tc_t g_mutex_socket; +static tc_t g_mutex_thread_list; +static tc_p mutex_device_port = (tc_p)NULL; +static tc_p mutex_pcon_port = (tc_p)NULL; +static tc_p mutex_port = (tc_p)NULL; +static tc_p mutex_parent = (tc_p)NULL; +static tc_p mutex_portop = (tc_p)NULL; +static tc_p mutex_reqid = (tc_p)NULL; +static tc_p mutex_socket = (tc_p)NULL; +static tc_p mutex_thread_list = (tc_p)NULL; + +static int APP_CC rdpport_cycle(rdpport_t *); +static int APP_CC issue_port_cmd(rdpport_t *, const rdpdr_packet_t *restrict); + +static int APP_CC get_reqid_port(int *); +static int APP_CC free_reqid_port(int); +static int APP_CC init_reqids_port(void); +static int APP_CC retrieve_reqid_port(int); +static int APP_CC get_mutex_port(int, tc_p *); +static int APP_CC get_cv_port(int, tc_p *); +static int APP_CC ntstatus_to_errcode(DWORD); + +extern char * APP_CC ntstatus_string(uint32_t); + +static int APP_CC parent_data_in_port(struct trans *); + + +/*****************************************************************************/ +/***** child process-related section ******/ +/*****************************************************************************/ + + +/*****************************************************************************/ +static int APP_CC +parent_data_in_port(struct trans * trans) { + struct stream * s = (struct stream *)NULL; + int rdpport_opcode = 0; + int rdpport_reply = 0; + int size = 0; + int error = 0; + int fault = 0; + int fhandle = 0; + int uniqid = 0; + int fdone = 0; + uint32_t magic = 0; + uint32_t device_id = 0; + uint32_t crc32 = 0; + uint32_t calc_crc32 = 0; + rdpport_t * port = (rdpport_t *)NULL; + BYTE buf[MAX_STREAM]; + + MDBGLOG("port","parent_data_in_port(): called"); + + g_memset((BYTE *)buf,0,sizeof(BYTE)*MAX_STREAM); + + if (trans == 0) { + return 0; + } + //TC_MUTEX_LOCK((tc_p)mutex_pcon_port); + //TC_MUTEX_LOCK((tc_p)mutex_parent); + s = (struct stream *)trans_get_in_s(trans); + in_uint32_le(s, magic); + in_uint32_le(s, rdpport_reply); + in_uint32_le(s, size); + in_uint32_le(s, device_id); + in_uint32_le(s, fhandle); + in_uint32_le(s, uniqid); + in_uint32_le(s, crc32); + if (size > 0) { + error = trans_force_read(trans, size); + calc_crc32 = Crc32_ComputeBuf(0, (void *)((char *)(s->p) + 28), size); + MDBGLOG("redir", "INFO\t[%s()]: crc32 = 0x%8.8x, calc_crc32 = 0x%8.8x", __func__, crc32, calc_crc32); + } + if (error == 0) { + /* the entire message block has been read in, so process it: */ + fault = ((rdpport_reply | RDPPORT_ERROR) == rdpport_reply) ? 1 : 0; + rdpport_opcode = rdpport_reply & (~(RDPPORT_REPLY | RDPPORT_ERROR)); + MDBGLOG("port"," ** parent_data_in_port(): rdpport_opcode = 0x%8.8x; rdpport_reply = 0x%8.8x; fault = %d; device_id = %d; uniqid = %d",rdpport_opcode,rdpport_reply,fault,device_id,uniqid); + if (fault > 0) { + NTSTATUS iostatus = { .Value = 0x00000000 }; + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + char * nterr = (char *)NULL; + + TC_MUTEX_LOCK((tc_p)mutex_portop); + in_uint32_le(s, iostatus.Value); + + nterr = ntstatus_string(iostatus.Value); + MDBGLOG("port"," --> FAULT: \"%s\" (status = 0x%8.8x)",nterr,iostatus.Value); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + if (reqid > -1) { + get_mutex_port(reqid, &lmut); + if (lmut != 0) { + TC_MUTEX_LOCK((tc_p)lmut); + TC_MUTEX_UNLOCK((tc_p)mutex_portop); + cbdata->IoStatus.Value = iostatus.Value; + get_cv_port(reqid, &lcv); + if (lcv != 0) { + TC_COND_SIGNAL((tc_p)lcv); + } + } + } + else { + lmut = mutex_portop; + } + if (lmut != 0) { + TC_MUTEX_UNLOCK((tc_p)lmut); + } + } + else switch(rdpport_opcode) { + case RDPPORT_OPEN: + MDBGLOG("port"," ^^ (RDPPORT_OPEN)"); + { + DR_DRIVE_CREATE_RSP iorsp; + int reqid = -1; + int tsize = 0; + callback * cbdata = NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + LOCAL_STREAM(v); + TC_MUTEX_LOCK((tc_p)mutex_portop); + reqid = retrieve_reqid_port(uniqid); + cbdata = &(g_reqids[reqid]); + get_mutex_port(reqid, &lmut); + TC_MUTEX_LOCK((tc_p)lmut); + TC_MUTEX_UNLOCK((tc_p)mutex_portop); + get_cv_port(reqid, &lcv); + construct_DR_DRIVE_CREATE_RSP(&iorsp); + if (size > 0 && size < MAX_STREAM) { + get_DR_DRIVE_CREATE_RSP(&iorsp, s); + } + cbdata->FileId = iorsp.DeviceCreateResponse.FileId; + MDBGLOG("port"," --> FileId = %d; fhandle = %d",cbdata->FileId,fhandle); + send_DR_DRIVE_CREATE_RSP(&iorsp, v); + s_mark_end(v); + tsize = v->end - v->data; + //g_hexdump_file("/tmp/taskq_port_open_reply.hexdump",v->data,tsize); + TC_COND_SIGNAL((tc_p)lcv); + TC_MUTEX_UNLOCK((tc_p)lmut); + } + break; + case RDPPORT_READ: + MDBGLOG("port"," ^^ (RDPPORT_READ)"); + { + DR_DRIVE_READ_RSP iorsp; + int reqid = -1; + int tsize = 0; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + LOCAL_STREAM(v); + TC_MUTEX_LOCK((tc_p)mutex_portop); + reqid = retrieve_reqid_port(uniqid); + cbdata = &(g_reqids[reqid]); + get_mutex_port(reqid, &lmut); + TC_MUTEX_LOCK((tc_p)lmut); + TC_MUTEX_UNLOCK((tc_p)mutex_portop); + construct_DR_READ_RSP(&iorsp); + if (size > 0 && size < MAX_STREAM) { + iorsp.ReadData = cbdata->userdata; + get_DR_READ_RSP(&iorsp, s); + } + cbdata->length = iorsp.Length; + send_DR_READ_RSP(&iorsp, v); + s_mark_end(v); + tsize = v->end - v->data; + get_cv_port(reqid,&lcv); + TC_COND_SIGNAL((tc_p)lcv); + TC_MUTEX_UNLOCK((tc_p)lmut); + MDBGLOG("port"," ^^ (RDPPORT_READ): iorsp.Length = %d; iorsp.ReadData = \"%s\"",iorsp.Length,iorsp.ReadData); + } + break; + case RDPPORT_WRITE: + MDBGLOG("port"," ^^ (RDPPORT_WRITE)"); + { + DR_DRIVE_WRITE_RSP iorsp; + int reqid = -1; + //callback * cbdata = (callback *)NULL; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + TC_MUTEX_LOCK((tc_p)mutex_portop); + reqid = retrieve_reqid_port(uniqid); + if (reqid < 0) { + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + } + else { + cbdata = &(g_reqids[reqid]); + } + //cbdata = &(g_reqids[uniqid]); +// reqid = retrieve_reqid_port(uniqid); +// cbdata = &(g_reqids[reqid]); + //reqid = cbdata->opid; + get_mutex_port(reqid, &lmut); + TC_MUTEX_LOCK((tc_p)lmut); + TC_MUTEX_UNLOCK((tc_p)mutex_portop); + construct_DR_WRITE_RSP(&iorsp); + get_DR_WRITE_RSP(&iorsp, s); + cbdata->length = iorsp.Length; + get_cv_port(reqid,&lcv); + TC_COND_SIGNAL((tc_p)lcv); + TC_MUTEX_UNLOCK((tc_p)lmut); + } + break; + case RDPPORT_IOCTL: + MDBGLOG("port"," ^^ (RDPPORT_IOCTL)"); + { + DR_CONTROL_RSP iorsp; + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + TC_MUTEX_LOCK((tc_p)mutex_portop); + reqid = retrieve_reqid_port(uniqid); + if (reqid < 0) { + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + } + else { + cbdata = &(g_reqids[reqid]); + } + get_mutex_port(reqid, &lmut); + TC_MUTEX_LOCK((tc_p)lmut); + TC_MUTEX_UNLOCK((tc_p)mutex_portop); + construct_DR_CONTROL_RSP(&iorsp); + iorsp.OutputBufferLength = cbdata->length; + if (cbdata->userdata != NULL) { + iorsp.OutputBuffer = cbdata->userdata; + } + else if (cbdata->length > 0) { + iorsp.OutputBuffer = (void *)g_malloc(cbdata->length, 1); + } + MDBGLOG("port"," -- about to call get_DR_CONTROL_RDP()..."); + get_DR_CONTROL_RSP(&iorsp, s); + MDBGLOG("port"," -- get_DR_CONTROL_RDP() done."); + cbdata->length = iorsp.OutputBufferLength; + if (cbdata->length > 0) { + cbdata->userdata = (BYTE *)g_malloc(cbdata->length, 1); + g_memcpy(cbdata->userdata, iorsp.OutputBuffer, cbdata->length); + } + if ((cbdata->flags & CBFLAG_FUNC) || (cbdata->flags & CBFLAG_SUPPRESS) || ((cbdata->flags & CBFLAG_CMD) && (cbdata->cmd == IOCTL_SERIAL_WAIT_ON_MASK))) { + MDBGLOG("port"," ^^ (RDPPORT_IOCTL): about to execute callback function..."); + if (cbdata->call != NULL && g_stop < 1) { + callback * tcb = (callback *)NULL; + tc_t * lthread = (tc_t *)NULL; + thread_head_t * thead = (thread_head_t *)NULL; + thead = (thread_head_t *)g_malloc(sizeof(thread_head_t), 1); + lthread = (tc_t *)g_malloc(sizeof(tc_t), 1); + thead->thread = lthread; + tcb = (callback *)g_malloc(sizeof(callback), 1); + g_memcpy(tcb, cbdata, sizeof(callback)); + TC_MUTEX_LOCK((tc_p)mutex_thread_list); + if (g_thread_list == NULL) { + thead->next = thead; + thead->prev = thead; + } + else { + thead->next = g_thread_list; + thead->prev = g_thread_list->prev; + g_thread_list->prev = thead; + } + g_thread_list = thead; + TC_THREAD_INIT(&(thead->thread->thread), cbdata->call, tcb); + TC_MUTEX_UNLOCK((tc_p)mutex_thread_list); + TC_MUTEX_UNLOCK((tc_p)lmut); + lmut = NULL; + } + else { + //MDBGLOG("port"," ^^ (RDPPORT_IOCTL): callback ERROR"); + } + MDBGLOG("port"," ^^ (RDPPORT_IOCTL): callback done."); + } + else if (!(cbdata->flags & CBFLAG_SUPPRESS)) { + MDBGLOG("port"," ^^ (RDPPORT_IOCTL): about to signal lcv..."); + get_cv_port(reqid,&lcv); + if (lcv != 0) { + TC_COND_SIGNAL((tc_p)lcv); + } + else { + MDBGLOG("port"," ^^ (RDPPORT_IOCTL): ERROR (lcv == 0)"); + } + MDBGLOG("port"," ^^ (RDPPORT_IOCTL): lcv signaled."); + } +// if (lmut > -1) { + if (lmut > (tc_p)NULL) { + TC_MUTEX_UNLOCK((tc_p)lmut); + } + MDBGLOG("port"," ^^ (RDPPORT_IOCTL): iorsp.OutputBufferLength = %d",iorsp.OutputBufferLength); + } + break; + case RDPPORT_CLOSE: + MDBGLOG("port"," ^^ (RDPPORT_CLOSE)"); + { + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + TC_MUTEX_LOCK((tc_p)mutex_portop); + reqid = retrieve_reqid_port(uniqid); + if (reqid < 0) { + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + } + else { + cbdata = &(g_reqids[reqid]); + } +// reqid = retrieve_reqid_port(uniqid); +// cbdata = &(g_reqids[reqid]); + //reqid = cbdata->opid; + get_mutex_port(reqid, &lmut); + TC_MUTEX_LOCK((tc_p)lmut); + TC_MUTEX_UNLOCK((tc_p)mutex_portop); + get_cv_port(reqid,&lcv); + TC_COND_SIGNAL((tc_p)lcv); + TC_MUTEX_UNLOCK((tc_p)lmut); + } + break; + case RDPPORT_INIT: + MDBGLOG("port"," ^^ (RDPPORT_INIT)"); + { + int reqid = -1; + callback * cbdata = (callback *)NULL; + filelist * lst = (filelist *)NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + } + break; + case RDPPORT_DESTROY: + MDBGLOG("port"," ^^ (RDPPORT_DESTROY)"); + break; + case RDPPORT_ERROR: + MDBGLOG("port"," ^^ (RDPPORT_ERROR)"); + break; + } + } + //TC_MUTEX_UNLOCK((tc_p)mutex_pcon_port); + //TC_MUTEX_UNLOCK((tc_p)mutex_parent); + return error; +} + + +/*****************************************************************************/ +static int socket_send(const int s, const struct rdpdr_packet * msg) { + unsigned int size = 0; + int err = 0; + int done = 0; + int cum = 0; + int rem = 0; + char buf[4096]; + void * pkt = (void *)buf; + + g_memset(buf, 0, sizeof(char) * 4096); + + TC_MUTEX_LOCK((tc_p)mutex_socket); + size = sizeof(struct rdpdr_packet_header) + (sizeof(uint8_t) * msg->size); + + g_memcpy(buf, msg, size); + err = g_tcp_send(s, pkt, size, 0); + TC_MUTEX_UNLOCK((tc_p)mutex_socket); + + return err; +} + + +/*****************************************************************************/ +/*****************************************************************************/ + + +typedef struct _handle_port_loop_args { + rdpport_t * port; + struct trans * pcon; + tbus objs[2]; + int num_objs; + int timeout; + int check_parent; + int check_device; +} handle_port_loop_args; + +static void * APP_CC +loop_parent_port(void * inargs) { + handle_port_loop_args * largs = (handle_port_loop_args *)inargs; + rdpport_t * port = largs->port; + struct trans * pcon = largs->pcon; + tbus * objs = (tbus *)(largs->objs); + int num_objs = largs->num_objs; + int timeout = largs->timeout; + int check_parent = largs->check_parent; + int check_device = largs->check_device; + tbus obj = -1; + if (num_objs > 0 && check_parent > 0) { + obj = objs[0]; + } + objs = (tbus *)&obj; + num_objs = 1; + if (inargs != NULL && objs != NULL && num_objs > 0 && check_parent > 0) { + /* handle any inbound communication from the parent process: */ + while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) { + if ((check_parent > 0) && g_is_wait_obj_set(objs[0])) { + //TC_MUTEX_LOCK((tc_p)mutex_parent); + if (trans_check_wait_objs(pcon) != 0) { + MDBGLOG("port","ERROR [loop_parent_port()]: "); + break; + } + //TC_MUTEX_UNLOCK((tc_p)mutex_parent); + g_reset_wait_obj(objs[0]); + } + } + } + MDBGLOG("port","INFO\t[%s()]: exiting thread",__func__); + tc_thread_exit(NULL); +} + +static void * APP_CC +loop_device_port(void * inargs) { + handle_port_loop_args * largs = (handle_port_loop_args *)inargs; + rdpport_t * port = largs->port; + struct trans * pcon = largs->pcon; + tbus * objs = (tbus *)(largs->objs); + int tcnt = 0; + int num_objs = largs->num_objs; + int timeout = largs->timeout; + int check_parent = largs->check_parent; + int check_device = largs->check_device; + tbus obj = -1; + if (num_objs > 1 && check_device > 0) { + obj = objs[1]; + } + else if (num_objs == 1 && check_device > 0) { + obj = objs[0]; + } + objs = (tbus *)&obj; + num_objs = 1; + if (inargs != NULL && objs != NULL && num_objs > 0 && check_device > 0) { + rdp_irq_data_t * data = (rdp_irq_data_t *)NULL; + rdpdr_packet_t * reply = (rdpdr_packet_t *)NULL; + char buf[MAX_STREAM]; + reply = (rdpdr_packet_t *)buf; + data = (rdp_irq_data_t *)(&(reply->data)); + data->type = RDP_M_OPEN; + issue_port_cmd(port, reply); + data->type = RDP_M_START; + issue_port_cmd(port, reply); + /* handle communication from pseudo-device (i.e., the artificial serial or parallel port on the server): */ + while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) { + if (g_is_wait_obj_set(obj)) { + rdpport_cycle(port); + } + } + } + g_keep_going = 0; + tc_thread_exit(NULL); +} + +/*****************************************************************************/ +static int APP_CC +rdpport_cycle(rdpport_t * port) { + ptrdiff_t rv = 0; + ptrdiff_t res = 0; + tbus fd = 0; + size_t bufsize = 0; + unsigned char proceed = 0; + char buf[MAX_STREAM]; + + g_memset((char *)buf,0,sizeof(buf)); + g_port = port; + g_fd = port->child_sck; + fd = port->fd; + MDBGLOG("port","INFO\t[%s()]: called (fd = %d)",__func__,fd); + if (buf == NULL) { + MDBGLOG("port","ERROR\t[%s()]: failed to allocate read buffer",__func__); + rv = -1; + } + else { + while (!proceed) { + ptrdiff_t len = 0; + rdp_irq_data_t * data = (rdp_irq_data_t *)NULL; + rdpdr_packet_t * reply = (rdpdr_packet_t *)NULL; + char buf[MAX_STREAM]; + + g_memset(buf, 0, sizeof(char) * 4096); + reply = (rdpdr_packet_t *)buf; + data = (rdp_irq_data_t *)(&(reply->data)); + + res = g_file_read(fd,data->rx_buf,(MAX_STREAM - sizeof(rdp_irq_data_t))); + if (res == -EINTR) { + MDBGLOG("port","INFO\t[%s()]: continue...",__func__); + continue; + } + else if (res >= 0) { + MDBGLOG("port","INFO\t[%s()]: proceed = 1",__func__); + proceed = 1; + data->rx_len += res; + } + else if (res < 0) { + MDBGLOG("port","ERROR\t[%s()]: res = %d",__func__,res); + break; + } + + if (proceed) { + if (data->rx_len > 0) { + data->type = RDP_M_WRITE; + } + issue_port_cmd(port, reply); + g_memset(buf,0,sizeof(buf)); + } + } + } + return rv; +} + +static int APP_CC issue_port_cmd(rdpport_t * port, const rdpdr_packet_t *restrict ipkt) { + int rv = 0; + tbus fd = -1; + uint32_t crc32 = 0; + ptrdiff_t olen = 0; + ptrdiff_t len = 0; + unsigned char send_reply = 1; + void * odata = (void *)NULL; + struct stat st; + struct trans * pcon = (struct trans *)NULL; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + void * subdata = (void *)NULL; + struct stream * s = (struct stream *)NULL; + int retstat = 0; + int rdpport_opcode = 0x00000000; + ptrdiff_t size = 0x00000000; + int reqid = -1; + int uniqid = 0; + tbus fhandle = 0; + ptrdiff_t seqid = 0; + ptrdiff_t idx = 0; + int val = 0; + int ack = 0; + int cmd = 0; + size_t sublen = 0; + const uint32_t magic = RDP_PACKET_MAGIC; + uint32_t device_id = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + char * p = (char *)NULL; + rdpdr_packet_t *restrict reply = (rdpdr_packet_t *restrict)ipkt; + rdp_irq_data_t * data = (rdp_irq_data_t *)(&(reply->data)); + + fd = port->fd; + uniqid = reply->uniqid; + cmd = data->type; + sublen = data->rx_len; + subdata = (void *)(data->rx_buf); + fhandle = reply->fhandle; + + switch (cmd) { + case RDP_M_SETMCTRL: + { + uint32_t cmd = 0x00000000; + const uint32_t ibuflen = 0x00000000; + const uint32_t obuflen = 0x00000000; + const BYTE * ibuf = (const BYTE *)NULL; + const BYTE * obuf = (const BYTE *)NULL; + int set_rts = 0; + int set_dtr = 0; + uint32_t mreg = 0; + + // *** + // *** BEGIN: PART I + // *** + + TC_MUTEX_LOCK((tc_p)mutex_portop); + get_reqid_port(&reqid); + get_mutex_port(reqid, &lmutex); + TC_MUTEX_LOCK((tc_p)lmutex); + TC_MUTEX_UNLOCK((tc_p)mutex_portop); + + rdpport_opcode = RDPPORT_IOCTL; + size = 0; + uniqid = reqid; + + get_cv_port(reqid, &lcv); + + mreg |= (ibuflen == sizeof(uint8_t)) ? *((uint8_t *)(subdata)) : (ibuflen == sizeof(uint32_t)) ? *((uint32_t *)(subdata)) : 0x00000000; + MDBGLOG("port","INFO\t[%s()]: (IOCTL_SERIAL_SET_MODEM_CONTROL) mreg = 0x%8.8x",__func__,mreg); + set_dtr = (mreg & SERIAL_IOC_MCR_DTR) ? 1 : 0; + set_rts = (mreg & SERIAL_IOC_MCR_RTS) ? 1 : 0; + + cmd = (set_dtr) ? IOCTL_SERIAL_SET_DTR : IOCTL_SERIAL_CLR_DTR; + + get_cv_port(reqid, &lcv); + cbdata = &(g_reqids[reqid]); + cbdata->port = port; + cbdata->length = obuflen; + cbdata->userdata = (BYTE *)NULL; + cbdata->opcode = rdpport_opcode; + cbdata->cmd = cmd; + cbdata->flags = CBFLAG_PORT | CBFLAG_MUTEX | CBFLAG_INTERMEDIATE | CBFLAG_CMD; + + rdpport_opcode = RDPPORT_IOCTL; + size = 0; + uniqid = reqid; + + TC_MUTEX_LOCK((tc_p)mutex_pcon_port); + pcon = port->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpport_opcode); + out_uint32_le(s, size + (sizeof(cmd) + sizeof(ibuflen) + sizeof(obuflen) + ibuflen)); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = s_get_pos(s); + out_uint32_le(s, cmd); + out_uint32_le(s, ibuflen); + out_uint32_le(s, obuflen); + s_mark_end(s); + size = s->end - s->data; + if (s->end > p) { + *p_crc32 = Crc32_ComputeBuf((uint32_t)0, (void *)p, (size_t)(s->end - p)); + } + + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + TC_MUTEX_UNLOCK((tc_p)mutex_pcon_port); + + MDBGLOG("port","entering g_obj_wait loop:"); + tc_cond_wait((tc_p)lcv, (tc_p)lmutex); + MDBGLOG("port","exiting g_obj_wait loop."); + + // *** + // *** END: PART I + // *** + + // *** + // *** BEGIN: PART II (RTS) + // *** + + cmd = (set_rts) ? IOCTL_SERIAL_SET_RTS : IOCTL_SERIAL_CLR_RTS; + + get_cv_port(reqid, &lcv); + cbdata = &(g_reqids[reqid]); + cbdata->port = port; + cbdata->length = obuflen; + cbdata->userdata = (BYTE *)NULL; + cbdata->opcode = rdpport_opcode; + cbdata->cmd = cmd; + cbdata->flags = CBFLAG_PORT | CBFLAG_MUTEX | CBFLAG_INTERMEDIATE | CBFLAG_CMD; + + rdpport_opcode = RDPPORT_IOCTL; + size = 0; + uniqid = reqid; + + TC_MUTEX_LOCK((tc_p)mutex_pcon_port); + pcon = port->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpport_opcode); + out_uint32_le(s, size + (sizeof(cmd) + sizeof(ibuflen) + sizeof(obuflen) + ibuflen)); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = s_get_pos(s); + out_uint32_le(s, cmd); + out_uint32_le(s, ibuflen); + out_uint32_le(s, obuflen); + s_mark_end(s); + size = s->end - s->data; + if ((s->end - p) > 0) { + *p_crc32 = Crc32_ComputeBuf((uint32_t)0, (void *)p, (size_t)(s->end - p)); + } + + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + TC_MUTEX_UNLOCK((tc_p)mutex_pcon_port); + + MDBGLOG("port","entering g_obj_wait loop:"); + tc_cond_wait((tc_p)lcv, (tc_p)lmutex); + MDBGLOG("port","exiting g_obj_wait loop."); + + TC_MUTEX_UNLOCK((tc_p)lmutex); + cbdata->userdata = NULL; + free_reqid_port(reqid); + + } + MDBGLOG("port","INFO\t[%s()]: RDPUART_SETMCTRL done.", __func__); + break; + + case RDP_M_GETMCTRL: + { + + uint32_t cmd = 0x00000000; + uint32_t ibuflen = 0x00000000; + uint32_t obuflen = 0x00000000; + BYTE * ibuf = (BYTE *)NULL; + BYTE * obuf = (BYTE *)NULL; + unsigned long * mreg = (unsigned long *)NULL; + + TC_MUTEX_LOCK((tc_p)mutex_portop); + get_reqid_port(&reqid); + get_mutex_port(reqid, &lmutex); + TC_MUTEX_LOCK((tc_p)lmutex); + TC_MUTEX_UNLOCK((tc_p)mutex_portop); + + get_cv_port(reqid, &lcv); + cbdata = &(g_reqids[reqid]); + cbdata->port = port; + + rdpport_opcode = RDPPORT_IOCTL; + cmd = IOCTL_SERIAL_GET_MODEM_CONTROL; + obuflen = sizeof(unsigned long); + size = 0; + uniqid = reqid; + + TC_MUTEX_LOCK((tc_p)mutex_pcon_port); + pcon = port->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpport_opcode); + out_uint32_le(s, size + (sizeof(cmd) + sizeof(ibuflen) + sizeof(obuflen)) + ibuflen); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = s_get_pos(s); + out_uint32_le(s, cmd); + out_uint32_le(s, ibuflen); + out_uint32_le(s, obuflen); + if (ibuflen > 0 && ibuf != NULL) { + out_uint8a(s, ibuf, ibuflen); + } + s_mark_end(s); + size = s->end - s->data; + if ((s->end - p) > 0) { + *p_crc32 = Crc32_ComputeBuf((uint32_t)0, (void *)p, (size_t)(s->end - p)); + } + + //g_hexdump_file("/tmp/taskq_port_getmctrl.hexdump", s->data, size); + MDBGLOG("port"," ** rdpport_getmctrl(): sending [g_fd = %d, fhandle = %d]", g_fd, fhandle); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + MDBGLOG("port","sent."); + TC_MUTEX_UNLOCK((tc_p)mutex_pcon_port); + + MDBGLOG("port","entering g_obj_wait loop:"); + tc_cond_wait((tc_p)lcv, (tc_p)lmutex); + MDBGLOG("port","exiting g_obj_wait loop."); + + mreg = (unsigned long *)cbdata->userdata; + odata = cbdata->userdata; + olen = sizeof(unsigned long *); + + MDBGLOG("port"," .. MCR = 0x%8.8x", *mreg); + + cbdata->userdata = NULL; + TC_MUTEX_UNLOCK((tc_p)lmutex); + free_reqid_port(reqid); + + } + break; + + case RDP_M_GETSTATUS: + { + } + break; + + case RDP_M_OPEN: + { + uint32_t flags = 0x00000000; + uint32_t share = 0x00000000; + uint32_t options = 0x00000000; + uint32_t attributes = 0x00000000; + uint32_t access = 0x00000000; + + TC_MUTEX_LOCK((tc_p)mutex_portop); + get_reqid_port(&reqid); + get_mutex_port(reqid, &lmutex); + TC_MUTEX_LOCK((tc_p)lmutex); + TC_MUTEX_UNLOCK((tc_p)mutex_portop); + + get_cv_port(reqid, &lcv); + cbdata = &(g_reqids[reqid]); + cbdata->port = port; + + rdpport_opcode = RDPPORT_OPEN; + size = 0; + uniqid = reqid; + + flags |= (FILE_WRITE_DATA | FILE_READ_DATA); + share |= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; + access |= SYNCHRONIZE | FILE_READ_ATTRIBUTES; + options |= FILE_OPEN; + + cbdata->opcode = rdpport_opcode; + cbdata->uniqid = uniqid; + cbdata->CompletionId = uniqid; + cbdata->opid = reqid; + cbdata->fd = fd; + cbdata->type = 0; + cbdata->flags = CBFLAG_FINAL | CBFLAG_PORT; + + TC_MUTEX_LOCK((tc_p)mutex_pcon_port); + pcon = port->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpport_opcode); + out_uint32_le(s, size + (sizeof(flags) + sizeof(share) + sizeof(options) + sizeof(attributes))); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = s_get_pos(s); + out_uint32_le(s, flags); + out_uint32_le(s, share); + out_uint32_le(s, options); + out_uint32_le(s, attributes); + s_mark_end(s); + size = s->end - s->data; + if ((s->end - p) > 0) { + *p_crc32 = Crc32_ComputeBuf((uint32_t)0, (void *)p, (size_t)(s->end - p)); + } + + g_hexdump_file("/tmp/taskq_port_open.hexdump", s->data, size); + MDBGLOG("port"," ** rdpport_open(): sending [g_fd = %d]", g_fd); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + TC_MUTEX_UNLOCK((tc_p)mutex_pcon_port); + MDBGLOG("port","sent."); + + MDBGLOG("port","entering g_obj_wait loop:"); + tc_cond_wait((tc_p)lcv, (tc_p)lmutex); + MDBGLOG("port","exiting g_obj_wait loop."); + fhandle = cbdata->FileId; + + g_fhandle = fhandle; + port->fhandle = fhandle; + + if (cbdata->userdata != NULL) { + g_free(cbdata->userdata); + } + cbdata->userdata = NULL; + + olen = sizeof(uint32_t); + odata = (void *)g_malloc(olen, 1); + *((uint32_t *)odata) |= fhandle; + + TC_MUTEX_UNLOCK((tc_p)lmutex); + free_reqid_port(reqid); + + } + break; + + case RDP_M_CLOSE: + { + TC_MUTEX_LOCK((tc_p)mutex_portop); + get_reqid_port(&reqid); + get_mutex_port(reqid, &lmutex); + TC_MUTEX_LOCK((tc_p)lmutex); + TC_MUTEX_UNLOCK((tc_p)mutex_portop); + + fhandle = g_fhandle; + + get_cv_port(reqid, &lcv); + cbdata = &(g_reqids[reqid]); + cbdata->port = port; + + rdpport_opcode = RDPPORT_CLOSE; + size = 0; + uniqid = reqid; + + cbdata->opcode = rdpport_opcode; + cbdata->uniqid = uniqid; + cbdata->CompletionId = uniqid; + cbdata->opid = reqid; + cbdata->fd = fd; + cbdata->type = 0; + cbdata->flags = CBFLAG_FINAL | CBFLAG_PORT; + +// out_uint32_le(s, magic); +// p_crc32 = (uint32_t *)s_get_pos(s); +// out_uint32_le(s, crc32); +// p = s_get_pos(s); +// if ((s->end - p) > 0) { +// *p_crc32 = Crc32_ComputeBuf((uint32_t)0, (void *)p, (size_t)(s->end - p)); +// } + + TC_MUTEX_LOCK((tc_p)mutex_pcon_port); + pcon = port->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpport_opcode); + out_uint32_le(s, size); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + s_mark_end(s); + size = s->end - s->data; + + //g_hexdump_file("/tmp/taskq_port_close.hexdump", s->data, size); + MDBGLOG("port"," ** rdpport_close(): sending [g_fd = %d]", g_fd); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + MDBGLOG("port","sent."); + TC_MUTEX_UNLOCK((tc_p)mutex_pcon_port); + + MDBGLOG("port","entering g_obj_wait loop:"); + tc_cond_wait((tc_p)lcv, (tc_p)lmutex); + MDBGLOG("port","exiting g_obj_wait loop."); + + g_fhandle = -1; + port->fhandle = -1; + + TC_MUTEX_UNLOCK((tc_p)lmutex); + free_reqid_port(reqid); + } + break; + + case RDP_M_READ: + { + + uint32_t obuflen = 0x00000001; + const uint64_t offset = 0x0000000000000000; + int lreqid = -1; + tc_p llmutex = (tc_p)NULL; + + get_reqid_port(&lreqid); + get_mutex_port(lreqid, &llmutex); + TC_MUTEX_LOCK((tc_p)llmutex); + + get_cv_port(lreqid, &lcv); + cbdata = &(g_reqids[lreqid]); + cbdata->port = port; + cbdata->userdata = (void *)g_malloc(1, 1); + + rdpport_opcode = RDPPORT_READ; + size = 0; + uniqid = lreqid; + + cbdata->opcode = rdpport_opcode; + cbdata->uniqid = uniqid; + cbdata->CompletionId = uniqid; + cbdata->opid = lreqid; + cbdata->fd = fd; + cbdata->type = 0; + cbdata->flags = CBFLAG_FINAL | CBFLAG_PORT; + + TC_MUTEX_LOCK((tc_p)mutex_pcon_port); + pcon = port->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpport_opcode); + out_uint32_le(s, (size + sizeof(uint32_t) + sizeof(uint64_t))); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = s_get_pos(s); + out_uint32_le(s, obuflen); + out_uint64_le(s, offset); + s_mark_end(s); + size = s->end - s->data; + if ((s->end - p) > 0) { + *p_crc32 = Crc32_ComputeBuf((uint32_t)0, (void *)p, (size_t)(s->end - p)); + } + + //g_hexdump_file("/tmp/taskq_port_read.hexdump", s->data, size); + MDBGLOG("port"," ** rdpport_read(): sending [g_fd = %d, fhandle = %d, obuflen = %d]", g_fd, fhandle, obuflen); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + MDBGLOG("port","sent."); + TC_MUTEX_UNLOCK((tc_p)mutex_pcon_port); + + MDBGLOG("port","entering g_obj_wait loop:"); + tc_cond_wait((tc_p)lcv, (tc_p)llmutex); + MDBGLOG("port","exiting g_obj_wait loop."); + + odata = cbdata->userdata; + olen = obuflen; + + MDBGLOG("port"," .. *odata = %c", *((unsigned char *)odata)); + + cbdata->userdata = NULL; + TC_MUTEX_UNLOCK((tc_p)llmutex); + free_reqid_port(lreqid); + + g_read_outstanding = 0; + + } + break; + + case RDP_M_WRITE: + { + const uint32_t ibuflen = (const uint32_t)sublen; + const uint64_t offset = 0x0000000000000000; + BYTE * ibuf = (BYTE *)subdata; + + TC_MUTEX_LOCK((tc_p)mutex_portop); + get_reqid_port(&reqid); + get_mutex_port(reqid, &lmutex); + TC_MUTEX_LOCK((tc_p)lmutex); + TC_MUTEX_UNLOCK((tc_p)mutex_portop); + + get_cv_port(reqid, &lcv); + cbdata = &(g_reqids[reqid]); + cbdata->port = port; + + rdpport_opcode = RDPPORT_WRITE; + size = 0; + uniqid = reqid; + + cbdata->opcode = rdpport_opcode; + cbdata->uniqid = uniqid; + cbdata->CompletionId = uniqid; + cbdata->opid = reqid; + cbdata->fd = fd; + cbdata->type = 0; + cbdata->flags = CBFLAG_FINAL | CBFLAG_PORT; + + TC_MUTEX_LOCK((tc_p)mutex_pcon_port); + pcon = port->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpport_opcode); + out_uint32_le(s, (size + sizeof(uint32_t) + sizeof(uint64_t) + ibuflen)); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = s_get_pos(s); + out_uint32_le(s, ibuflen); + out_uint64_le(s, offset); + if (ibuflen > 0 && ibuf != NULL) { + out_uint8a(s, ibuf, ibuflen); + } + s_mark_end(s); + size = s->end - s->data; + if ((s->end - p) > 0) { + *p_crc32 = Crc32_ComputeBuf((uint32_t)0, (void *)p, (size_t)(s->end - p)); + } + + MDBGLOG("port"," ** rdpport_write(): sending [g_fd = %d, fhandle = %d, ibuflen = %d]", g_fd, fhandle, ibuflen); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + MDBGLOG("port","sent."); + TC_MUTEX_UNLOCK((tc_p)mutex_pcon_port); + + MDBGLOG("port","entering g_obj_wait loop:"); + tc_cond_wait((tc_p)lcv, (tc_p)lmutex); + MDBGLOG("port","exiting g_obj_wait loop."); + + MDBGLOG("port"," .. *ibuf = %c", *((unsigned char *)ibuf)); + + cbdata->userdata = NULL; + TC_MUTEX_UNLOCK((tc_p)lmutex); + free_reqid_port(reqid); + + } + break; + + case RDP_M_DATA: + { + } + break; + + case RDP_M_START: + { + + /* + * + * Upon startup, this code simulates UART interrupts by + * causing a "DR_CONTROL_REQ"-type IRP to be issued to the + * RDP client, with a command of IOCTL_SERIAL_SET_WAIT_MASK + * followed by a IOCTL_SERIAL_WAIT_ON_MASK command (which only + * returns when the specified wait mask criteria are met). + * Other IRPs may be processed normally (and simultaneously) + * while the DR_CONTROL_REQ remains pending. This "dormant" + * behavior permits the illusion of interrupt-based operation. + * + */ + + uint32_t cmd = 0x00000000; + uint32_t ibuflen = 0x00000000; + uint32_t obuflen = 0x00000000; + uint32_t * mask = (uint32_t *)NULL; + BYTE * ibuf = (BYTE *)NULL; + BYTE * obuf = (BYTE *)NULL; + + mask = (uint32_t *)g_malloc(sizeof(uint32_t), 1); + + // *** + // *** BEGIN: PART I + // *** + + TC_MUTEX_LOCK((tc_p)mutex_portop); + get_reqid_port(&reqid); + get_mutex_port(reqid, &lmutex); + TC_MUTEX_LOCK((tc_p)lmutex); + TC_MUTEX_UNLOCK((tc_p)mutex_portop); + + rdpport_opcode = RDPPORT_IOCTL; + cmd = IOCTL_SERIAL_SET_WAIT_MASK; + *mask = SERIAL_EV_RXCHAR | SERIAL_EV_BREAK + | SERIAL_EV_CTS | SERIAL_EV_DSR + | SERIAL_EV_ERR | SERIAL_EV_RING + | SERIAL_EV_RLSD | SERIAL_EV_RXFLAG + | SERIAL_EV_TXEMPTY; + ibuflen = sizeof(*mask); + ibuf = (void *)mask; + size = 0; + uniqid = reqid; + + get_cv_port(reqid, &lcv); + cbdata = &(g_reqids[reqid]); + cbdata->port = port; + cbdata->length = 0; + cbdata->userdata = (BYTE *)NULL; + cbdata->opcode = rdpport_opcode; + cbdata->cmd = cmd; + cbdata->mask = *mask; + cbdata->flags = CBFLAG_PORT | CBFLAG_IRQ | CBFLAG_MUTEX | CBFLAG_INTERMEDIATE | CBFLAG_CMD | CBFLAG_MASK; + + TC_MUTEX_LOCK((tc_p)mutex_pcon_port); + pcon = port->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpport_opcode); + out_uint32_le(s, size + (sizeof(cmd) + sizeof(ibuflen) + sizeof(obuflen) + ibuflen)); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = s_get_pos(s); + out_uint32_le(s, cmd); + out_uint32_le(s, ibuflen); + out_uint32_le(s, obuflen); + if (ibuflen > 0 && ibuf != NULL) { + out_uint32_le(s, *ibuf); + } + s_mark_end(s); + size = s->end - s->data; + if ((s->end - p) > 0) { + *p_crc32 = Crc32_ComputeBuf((uint32_t)0, (void *)p, (size_t)(s->end - p)); + } + + MDBGLOG("port"," ** rdpport_setwaitmask(): sending [g_fd = %d, fhandle = %d, *mask = %d]", g_fd, fhandle, *mask); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + MDBGLOG("port","sent."); + TC_MUTEX_UNLOCK((tc_p)mutex_pcon_port); + + MDBGLOG("port","entering g_obj_wait loop:"); + tc_cond_wait((tc_p)lcv, (tc_p)lmutex); + MDBGLOG("port","exiting g_obj_wait loop."); + + TC_MUTEX_LOCK((tc_p)mutex_portop); + TC_MUTEX_UNLOCK((tc_p)lmutex); + free_reqid_port(reqid); + + MDBGLOG("port","\t- - - now, proceeding to IOCTL_SERIAL_WAIT_ON_MASK..."); + + // *** + // *** END: PART I + // *** + + // *** + // *** BEGIN: PART II + // *** + + get_reqid_port(&reqid); + get_mutex_port(reqid, &lmutex); + TC_MUTEX_LOCK((tc_p)lmutex); + TC_MUTEX_UNLOCK((tc_p)mutex_portop); + + cbdata = &(g_reqids[reqid]); + + rdpport_opcode = RDPPORT_IOCTL; + cmd = IOCTL_SERIAL_WAIT_ON_MASK; + ibuflen = 0; + ibuf = NULL; + obuflen = sizeof(ULONG); + size = 0; + uniqid = reqid; + + cbdata->call = &rdp_irq_callback; + cbdata->cmd = cmd; + cbdata->flags = CBFLAG_PORT | CBFLAG_IRQ | CBFLAG_MUTEX | CBFLAG_FUNC | CBFLAG_CMD | CBFLAG_MASK; + cbdata->opid = reqid; + cbdata->CompletionId = uniqid; + cbdata->uniqid = uniqid; + cbdata->port = port; + cbdata->FileId = fhandle; + cbdata->opcode = rdpport_opcode; + cbdata->mask = *mask; + + TC_MUTEX_LOCK((tc_p)mutex_pcon_port); + g_irq_cb = cbdata; + g_irq_idx = reqid; + pcon = port->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpport_opcode); + out_uint32_le(s, size + (sizeof(cmd) + sizeof(ibuflen) + sizeof(obuflen) + ibuflen)); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = s_get_pos(s); + out_uint32_le(s, cmd); + out_uint32_le(s, ibuflen); + out_uint32_le(s, obuflen); + s_mark_end(s); + size = s->end - s->data; + if ((s->end - p) > 0) { + *p_crc32 = Crc32_ComputeBuf((uint32_t)0, (void *)p, (size_t)(s->end - p)); + } + + //g_hexdump_file("/tmp/taskq_port_waitonmask.hexdump", s->data, size); + MDBGLOG("port"," ** rdpport_waitonmask(): sending [g_fd = %d, fhandle = %d, reqid = %d, cbdata->CompletionId = %d, cbdata->uniqid = %d, cbdata->opid = %d, cbdata->cmd = 0x%8.8x]", g_fd, fhandle, reqid, cbdata->CompletionId, cbdata->uniqid, cbdata->opid, cbdata->cmd); + trans_force_write(pcon); + TC_MUTEX_UNLOCK((tc_p)lmutex); + g_memset(s->data,0,MAX_STREAM); + MDBGLOG("port","sent."); + //MDBGLOG("port"," - - - WAITING ON MASK..."); + g_stop = 0; + TC_MUTEX_UNLOCK((tc_p)mutex_pcon_port); + //MDBGLOG("port"," - - - ..."); + + // *** + // *** END: PART II + // *** + } + MDBGLOG("port", "RDPUART_START: done."); + break; + + case RDP_M_STOP: + { + g_stop = 1; + + uint32_t cmd = 0x00000000; + uint32_t ibuflen = 0x00000000; + uint32_t obuflen = 0x00000000; + uint32_t * mask = (uint32_t *)NULL; + BYTE * ibuf = (BYTE *)NULL; + BYTE * obuf = (BYTE *)NULL; + + mask = (uint32_t *)g_malloc(sizeof(uint32_t), 1); + + TC_MUTEX_LOCK((tc_p)mutex_portop); + get_reqid_port(&reqid); + get_mutex_port(reqid, &lmutex); + TC_MUTEX_LOCK((tc_p)lmutex); + TC_MUTEX_UNLOCK((tc_p)mutex_portop); + + rdpport_opcode = RDPPORT_IOCTL; + cmd = IOCTL_SERIAL_SET_WAIT_MASK; + *mask = 0x00000000; + ibuflen = sizeof(*mask); + ibuf = (void *)mask; + size = 0; + uniqid = reqid; + + get_cv_port(reqid, &lcv); + cbdata = &(g_reqids[reqid]); + cbdata->port = port; + cbdata->length = 0; + cbdata->userdata = (BYTE *)NULL; + cbdata->opcode = rdpport_opcode; + cbdata->cmd = cmd; + cbdata->mask = *mask; + cbdata->flags = CBFLAG_PORT | CBFLAG_IRQ | CBFLAG_MUTEX | CBFLAG_FINAL | CBFLAG_CMD | CBFLAG_MASK; + + TC_MUTEX_LOCK((tc_p)mutex_pcon_port); + pcon = port->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpport_opcode); + out_uint32_le(s, size + (sizeof(cmd) + sizeof(ibuflen) + sizeof(obuflen) + ibuflen)); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = s_get_pos(s); + out_uint32_le(s, cmd); + out_uint32_le(s, ibuflen); + out_uint32_le(s, obuflen); + if (ibuflen > 0 && ibuf != NULL) { + out_uint32_le(s, *ibuf); + } + s_mark_end(s); + size = s->end - s->data; + if ((s->end - p) > 0) { + *p_crc32 = Crc32_ComputeBuf((uint32_t)0, (void *)p, (size_t)(s->end - p)); + } + + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + TC_MUTEX_UNLOCK((tc_p)mutex_pcon_port); + + MDBGLOG("port","entering g_obj_wait loop:"); + tc_cond_wait((tc_p)lcv, (tc_p)lmutex); + MDBGLOG("port","exiting g_obj_wait loop."); + + TC_MUTEX_UNLOCK((tc_p)lmutex); + free_reqid_port(reqid); + + } + break; + + case RDP_M_GETBAUD: + { + } + break; + + case RDP_M_SETBAUD: + { + } + break; + + case RDP_M_TXEMPTY: + { + uint32_t cmd = 0x00000000; + uint32_t ibuflen = 0x00000000; + uint32_t obuflen = 0x00000000; + BYTE * ibuf = (BYTE *)NULL; + BYTE * obuf = (BYTE *)NULL; + SERIAL_STATUS lserstat; + SERIAL_STATUS * serstat = (SERIAL_STATUS *)NULL; + + g_memset(&lserstat, 0, sizeof(SERIAL_STATUS)); + serstat = &lserstat; + + TC_MUTEX_LOCK((tc_p)mutex_portop); + get_reqid_port(&reqid); + get_mutex_port(reqid, &lmutex); + TC_MUTEX_LOCK((tc_p)lmutex); + TC_MUTEX_UNLOCK((tc_p)mutex_portop); + + get_cv_port(reqid, &lcv); + cbdata = &(g_reqids[reqid]); + cbdata->port = port; + cbdata->userdata = (void *)(&lserstat); + + rdpport_opcode = RDPPORT_IOCTL; + cmd = IOCTL_SERIAL_GET_COMMSTATUS; + obuflen = sizeof(SERIAL_STATUS); + size = 0; + uniqid = reqid; + + cbdata->opcode = rdpport_opcode; + cbdata->uniqid = uniqid; + cbdata->CompletionId = uniqid; + cbdata->opid = reqid; + cbdata->fd = fd; + cbdata->type = 0; + cbdata->flags = CBFLAG_FINAL | CBFLAG_PORT; + + TC_MUTEX_LOCK((tc_p)mutex_pcon_port); + pcon = port->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpport_opcode); + out_uint32_le(s, size + (sizeof(cmd) + sizeof(ibuflen) + sizeof(obuflen)) + ibuflen); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)s_get_pos(s); + out_uint32_le(s, crc32); + p = s_get_pos(s); + out_uint32_le(s, cmd); + out_uint32_le(s, ibuflen); + out_uint32_le(s, obuflen); + if (ibuflen > 0 && ibuf != NULL) { + out_uint8a(s, ibuf, ibuflen); + } + s_mark_end(s); + size = s->end - s->data; + if ((s->end - p) > 0) { + *p_crc32 = Crc32_ComputeBuf((uint32_t)0, (void *)p, (size_t)(s->end - p)); + } + + //g_hexdump_file("/tmp/taskq_port_txempty.hexdump", s->data, size); + MDBGLOG("port"," ** rdpport_txempty(): sending [g_fd = %d, fhandle = %d]", g_fd, fhandle); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + MDBGLOG("port","sent."); + TC_MUTEX_UNLOCK((tc_p)mutex_pcon_port); + + MDBGLOG("port","entering g_obj_wait loop:"); + tc_cond_wait((tc_p)lcv, (tc_p)lmutex); + MDBGLOG("port","exiting g_obj_wait loop."); + + olen = sizeof(unsigned char); + odata = (void *)g_malloc(olen, 1); + *((unsigned char *)odata) = (serstat->AmountInOutQueue == 0) ? 1 : 0; + + MDBGLOG("port"," .. serstat->AmountInOutQueue = %d", serstat->AmountInOutQueue); + + cbdata->userdata = NULL; + TC_MUTEX_UNLOCK((tc_p)lmutex); + free_reqid_port(reqid); + } + break; + + case RDP_M_TXFULL: + { + } + break; + + case RDP_M_TXSTOP: + { + } + break; + + case RDP_M_TXSTART: + { + } + break; + + case RDP_M_RXEMPTY: + { + } + break; + + case RDP_M_RXFULL: + { + } + break; + + case RDP_M_RXSTOP: + { + } + break; + + case RDP_M_RXSTART: + { + } + break; + + case RDP_M_MSENABLE: + { + } + break; + + case RDP_M_BREAKCTL: + { + } + break; + + case RDP_M_SETTERMIOS: + { + } + break; + + case RDP_M_IOCTL: + { + } + break; + + case RDP_M_ASYNC: + { + } + break; + + case RDP_M_REPLY: + { + } + break; + + default: + { + } + break; + } + if (send_reply > 0) { + unsigned char * tp = (unsigned char *)NULL; + unsigned char tbuf[4096]; + rdpdr_packet_t * pkt = (rdpdr_packet_t *)tbuf; + memset(pkt, 0, sizeof(rdpdr_packet_t)); + pkt->size = olen; + if (olen > 0 && odata != NULL) { + g_memcpy(&(pkt->data), odata, olen); + } + len = socket_send(fd, pkt); + } + + return rv; +} + +/*****************************************************************************/ +rdpport_t * APP_CC +rdpport_main(int type, int seq) { + rdpport_t * rv = (rdpport_t *)NULL; + + rv = (rdpport_t *)g_malloc(sizeof(rdpport_t), 1); + rv->type = type; + rv->fd = -1; + + MDBGLOG("port","rdpport_main(): done."); + + return rv; +} + +/*****************************************************************************/ +int APP_CC +handle_port(tbus sck, rdpport_t * port) { + int rv = 0; + int brk = 0; + tbus s = 0; + tbus fd = 0; + tbus objs[2] = { -1, -1 }; + int num_objs = 0; + int timeout = 0; + int check_parent = 0; + int check_device = 0; + struct trans * pcon = (struct trans *)NULL; + callback cb; + handle_port_loop_args largs; + tc_t thread_parent; + tc_t thread_device; + tc_t thread_poll; + int node_num = 0; + const char node_base[] = "/tmp/.sock_rdp_%d"; + char node_buf[256]; + + // MDBGLOG("port","handle_port(): sck = %d", sck); + + g_memset(node_buf,0,sizeof(node_buf)); + g_memset(&cb,0,sizeof(callback)); + g_memset(&largs,0,sizeof(handle_port_loop_args)); + g_memset(&thread_parent,0,sizeof(tc_t)); + g_memset(&thread_device,0,sizeof(tc_t)); + g_memset(&thread_poll,0,sizeof(tc_t)); + + g_keep_going = 1; + + //mut = (tbus)&g_mutex; + mutex_pcon_port = (tc_p)&g_mutex_pcon_port; + mutex_port = (tc_p)&g_mutex_port; + mutex_portop = (tc_p)&g_mutex_portop; + mutex_parent = (tc_p)&g_mutex_parent; + mutex_device_port = (tc_p)&g_mutex_device_port; + mutex_reqid = (tc_p)&g_mutex_reqid; + mutex_socket = (tc_p)&g_mutex_socket; + mutex_thread_list = (tc_p)&g_mutex_thread_list; + //TC_MUTEX_INIT((tc_p)mut,NULL); + TC_MUTEX_INIT((tc_p)mutex_pcon_port,NULL); + TC_MUTEX_INIT((tc_p)mutex_port,NULL); + TC_MUTEX_INIT((tc_p)mutex_portop,NULL); + TC_MUTEX_INIT((tc_p)mutex_parent,NULL); + TC_MUTEX_INIT((tc_p)mutex_device_port,NULL); + TC_MUTEX_INIT((tc_p)mutex_reqid,NULL); + TC_MUTEX_INIT((tc_p)mutex_socket,NULL); + TC_MUTEX_INIT((tc_p)mutex_thread_list,NULL); + + TC_MUTEX_LOCK((tc_p)mutex_pcon_port); + TC_MUTEX_LOCK((tc_p)mutex_port); + + + MDBGLOG("port","handle_port(): (mutex_pcon_port and mutex_port locked) [1]"); + init_reqids_port(); + MDBGLOG("port","handle_port(): [init_reqids_port() done]"); + + /* set up pcon as a transmission channel to the parent */ + pcon = (struct trans *)trans_create((int)2, (int)MAX_STREAM, (int)MAX_STREAM); + MDBGLOG("port","handle_port(): [pcon created]"); + + pcon->trans_data_in = &parent_data_in_port; + pcon->header_size = 28; + rv = trans_attach(pcon, sck); + + MDBGLOG("port","handle_port(): [pcon attached] (rv = %d; sck = %d)",rv,sck); + + pcon->sck = sck; + port->ccon = pcon; + + TC_MUTEX_UNLOCK((tc_p)mutex_port); + TC_MUTEX_UNLOCK((tc_p)mutex_pcon_port); + + if (rv == 0) { + tbus fdm = -1; + tbus fds = -1; + char * sname = "/var/run/ttyRDP"; + + //MDBGLOG("port","handle_port(): (about to lock mutex_pcon_port and mutex_port) [1.5]"); + + TC_MUTEX_LOCK((tc_p)mutex_pcon_port); + TC_MUTEX_LOCK((tc_p)mutex_port); + + //MDBGLOG("port","handle_port(): (mutex_pcon_port and mutex_port locked) [2]"); + + /* add pcon to the set of monitored channels */ + if (pcon != NULL && pcon->sck > 0) { + objs[num_objs] = pcon->sck; + num_objs++; + check_parent = 1; + } + + //MDBGLOG("port","handle_port(): [3]"); + + //g_snprintf(node_buf, sizeof(node_buf) - 1, node_base, node_num); + //g_sprintf(node_buf, node_base, node_num); + s = g_tcp_local_socket(); + + //MDBGLOG("port","handle_port(): [4]"); + + g_file_delete(sname); + fdm = open("/dev/ptmx", O_RDWR); + grantpt(fdm); + unlockpt(fdm); + sname = ptsname(fdm); + + s = fdm; + + //MDBGLOG("port","handle_port(): [5]"); + if (s < 0) { + MDBGLOG("port", "ERROR\t[%s()]: failed to set up pseudo tty", __func__); + } + else { + //MDBGLOG("port","handle_port(): [7]"); + MDBGLOG("port", "INFO\t[%s()]: about to call g_create_wait_obj_from_socket(%d, 0)", __func__, s); + port->fd = g_create_wait_obj_from_socket(s, 0); + + // add the appropriate file descriptor to the set of monitored channels + if (port->fd > 0) { + objs[num_objs] = port->fd; + num_objs++; + check_device = 1; + MDBGLOG("port","handle_port(): added port->fd = \"%d\"",port->fd); + } + } + + TC_MUTEX_UNLOCK((tc_p)mutex_port); + TC_MUTEX_UNLOCK((tc_p)mutex_pcon_port); + + MDBGLOG("port","INFO\t[%s()]: pseudo tty = \"%s\", port->fd = %d, sck = %d, port->dos_name = %s",__func__,sname,port->fd,sck,((port->dos_name == NULL) ? "" : port->dos_name)); + + cb.port = port; + MDBGLOG("port","INFO\t[%s()]: calling rdp_addport()...", __func__); + rdp_addport(&cb); + + /* monitor the above channels for input and respond appropriately */ + if (num_objs > 0 && objs[0] > -1) { + + TC_MUTEX_LOCK((tc_p)mutex_pcon_port); + TC_MUTEX_LOCK((tc_p)mutex_port); + + //MDBGLOG("port","handle_port(): (mutex_pcon_port and mutex_port locked) [3]"); + + largs.port = port; + largs.pcon = pcon; + largs.objs[0] = objs[0]; + largs.objs[1] = objs[1]; + largs.num_objs = num_objs; + largs.timeout = timeout; + largs.check_parent = check_parent; + largs.check_device = check_device; + + TC_MUTEX_UNLOCK((tc_p)mutex_port); + TC_MUTEX_UNLOCK((tc_p)mutex_pcon_port); + + //MDBGLOG("port","handle_port(): (mutex_pcon_port and mutex_port unlocked) [3]"); + + if (objs != NULL && num_objs > 0 && (check_parent > 0 || check_device > 0)) { + + tc_t lattr; + g_memset(&lattr,0,sizeof(tc_t)); + tc_threadattr_init(&lattr); + tc_threadattr_setdetachstate(&lattr, TC_CREATE_JOINABLE); + + MDBGLOG("port","handle_port(): initializing threads..."); + + TC_THREAD_INIT_FULL(&(thread_parent.thread),(const tc_threadattr_t *)&lattr,&loop_parent_port,&largs); + TC_THREAD_INIT_FULL(&(thread_device.thread),(const tc_threadattr_t *)&lattr,&loop_device_port,&largs); + + MDBGLOG("port","handle_port(): initialized."); + MDBGLOG("port","handle_port(): waiting to join threads..."); + + TC_THREAD_JOIN(thread_parent.thread, NULL); + TC_THREAD_JOIN(thread_device.thread, NULL); + + MDBGLOG("port","handle_port(): joined."); + } + } + } + + MDBGLOG("port","handle_port(): done."); + + return rv; +} + + +/*****************************************************************************/ +static int APP_CC get_reqid_port(int * inarg) { + int rv = 0; + if (inarg == NULL) { + rv = -1; + } + else { + *inarg = -1; + //TC_MUTEX_LOCK((tc_p)mutex_reqid); + for (rv = 1; rv < MAX_REQID; rv++) { + if (g_reqids[rv].opid == -1) { + *inarg = rv; + g_reqids[rv].opid = rv; + TC_MUTEX_INIT((tc_p)&(g_reqids[rv].mutex),NULL); + TC_COND_CREATE((tc_p)&(g_reqids[rv].cv),NULL); + break; + } + } + //TC_MUTEX_UNLOCK((tc_p)mutex_reqid); + } + return rv; +} + +static int APP_CC free_reqid_port(int inarg) { + int rv = 0; + if (inarg < 0 || inarg > MAX_REQID) { + rv = -1; + } + else if (g_reqids[inarg].opid > -1 && g_reqids[inarg].opid <= MAX_REQID) { + TC_MUTEX_LOCK((tc_p)mutex_reqid); + TC_MUTEX_DEINIT(&(g_reqids[inarg].mutex)); + TC_COND_DEINIT(&(g_reqids[inarg].cv)); + g_memset(&(g_reqids[inarg]),0,sizeof(callback)); + g_reqids[inarg].opid = -1; + TC_MUTEX_UNLOCK((tc_p)mutex_reqid); + } + return rv; +} + +static int APP_CC init_reqids_port() { + int rv = 0; + MDBGLOG("port","init_reqids_port(): started"); + //TC_MUTEX_LOCK((tc_p)mutex_reqid); + g_memset((callback *)g_reqids,0,sizeof(callback)*MAX_REQID); + for (rv = 0; rv < MAX_REQID; rv++) { + g_reqids[rv].opid = -1; + } + //TC_MUTEX_UNLOCK((tc_p)mutex_reqid); + MDBGLOG("port","init_reqids_port(): done."); + rv = 0; + return rv; +} + +static int APP_CC retrieve_reqid_port(int uniqid) { + int rv = -1; + int found = 0; + + for (rv = 0; rv < MAX_REQID; rv++) { + if (g_reqids[rv].uniqid == uniqid) { + found = 1; + break; + } + } + if (found < 1) { + rv = -1; + } + + return rv; +} + +static int APP_CC get_mutex_port(int reqid, tc_p * inarg) { + int rv = 0; + + if (reqid >= 0 && reqid < MAX_REQID) { + //TC_MUTEX_LOCK((tc_p)mutex_reqid); + *inarg = (tc_p)&(g_reqids[reqid].mutex); + //TC_MUTEX_UNLOCK((tc_p)mutex_reqid); + } + else { + rv = -1; + } + return rv; +} + +static int APP_CC get_cv_port(int reqid, tc_p * inarg) { + int rv = 0; + if (reqid >= 0 && reqid < MAX_REQID) { + //TC_MUTEX_LOCK((tc_p)mutex_reqid); + *inarg = (tc_p)&(g_reqids[reqid].cv); + //TC_MUTEX_UNLOCK((tc_p)mutex_reqid); + } + else { + rv = -1; + } + return rv; +} + +static char * APP_CC rdpport_get_dircomponent(char * rv, const char * name) { + char * npos = (char *)NULL; + + if (name != NULL) { + npos = (char *)g_strrchr(name, (int)'/'); + if (npos > 0) { + if (rv == NULL) { + rv = (char *)g_malloc(sizeof(char) * ((npos - name) + 1), 1); + } + g_strncpy(rv, name, (npos - name)); + } + } + + return rv; +} + +/********************************************************/ +/* refactor a filename into canonical form */ +/********************************************************/ +static void APP_CC rdpport_clean_fname(char * name) { + char * p = (char *)NULL; + char * p2 = (char *)NULL; + int l = 0; + int modified = 1; + const char forbidden[] = {'/', '[', ']', ':', '|', '<', '>', '+', '=', ';', ',', '?', 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f}; + + if (name == NULL) { + return; + } + + MDBGLOG("port","rdpport_clean_fname() [%s]:\n", name); + + while (modified) { + modified = 0; + if ((p=strstr(name,"/./"))) { + modified = 1; + while (*p) { + p[0] = p[2]; + p++; + } + MDBGLOG("port", "\tclean 1 (/./) produced [%s]\n", name); + } + if ((p=strstr(name,"//"))) { + modified = 1; + while (*p) { + p[0] = p[1]; + p++; + } + MDBGLOG("port", "\tclean 2 (//) produced [%s]\n", name); + } + if (strcmp(name,"/../")==0) { + modified = 1; + name[1] = 0; + MDBGLOG("port", "\tclean 3 (^/../$) produced [%s]\n", name); + } + if ((p=strstr(name,"/../"))) { + modified = 1; + for (p2 = (p > name ? p-1 : p); p2 > name; p2--) { + if (p2[0] == '/') { + break; + } + } + if (p2 > name) p2++; + while (*p2) { + p2[0] = p[3]; + p2++; + p++; + } + MDBGLOG("port", "\tclean 4 (/../) produced [%s]\n", name); + } + + if (strcmp(name,"/..")==0) { + modified = 1; + name[1] = 0; + MDBGLOG("port", "\tclean 5 (^/..$) produced [%s]\n", name); + } + + l = strlen(name); + p = l>=3?(name+l-3):name; + if (strcmp(p,"/..")==0) { + modified = 1; + for (p2=p-1;p2>name;p2--) { + if (p2[0] == '/') break; + } + if (p2==name) { + p[0] = '/'; + p[1] = 0; + } else { + p2[0] = 0; + } + MDBGLOG("port", "\tclean 6 (/..) produced [%s]\n", name); + } + + l = strlen(name); + p = l>=2?(name+l-2):name; + if (strcmp(p,"/.")==0) { + modified = 1; + if (p == name) { + p[1] = 0; + } else { + p[0] = 0; + } + MDBGLOG("port", "\tclean 7 (/.) produced [%s]\n", name); + } + + if (strncmp(p=name,"./",2) == 0) { + modified = 1; + do { + p[0] = p[2]; + } while (*p++); + MDBGLOG("port", "\tclean 8 (^./) produced [%s]\n", name); + } + + l = strlen(p=name); + if (l > 1 && p[l-1] == '/') { + modified = 1; + p[l-1] = 0; + MDBGLOG("port", "\tclean 9 (/) produced [%s]\n", name); + } + } + + MDBGLOG("port","rdpport_clean_fname() done [%s].\n", name); +} + +static int APP_CC ntstatus_to_errcode(DWORD ntstat) { + int retstat = 0; + + switch (ntstat) { + case 0: + retstat = 0; + break; + case STATUS_ACCESS_DENIED: + case STATUS_ACCESS_VIOLATION: + case STATUS_NETWORK_ACCESS_DENIED: + case STATUS_UNSUCCESSFUL: + retstat = -EACCES; + break; + case STATUS_GUARD_PAGE_VIOLATION: + case STATUS_INVALID_PARAMETER: + case STATUS_BAD_DEVICE_TYPE: + case STATUS_BAD_NETWORK_NAME: + case STATUS_INVALID_VOLUME_LABEL: + case STATUS_BAD_TOKEN_TYPE: + case STATUS_INVALID_GROUP_ATTRIBUTES: + case STATUS_BAD_MASTER_BOOT_RECORD: + case STATUS_INVALID_OPLOCK_PROTOCOL: + case STATUS_INVALID_INFO_CLASS: + case STATUS_INVALID_DEVICE_REQUEST: + case STATUS_INVALID_SYSTEM_SERVICE: + case STATUS_ILLEGAL_INSTRUCTION: + case STATUS_INVALID_LOCK_SEQUENCE: + case STATUS_INVALID_VIEW_SIZE: + case STATUS_INVALID_FILE_FOR_SECTION: + case STATUS_INVALID_DISPOSITION: + case STATUS_INVALID_UNWIND_TARGET: + case STATUS_INVALID_PORT_ATTRIBUTES: + case STATUS_INVALID_PARAMETER_MIX: + case STATUS_OBJECT_NAME_INVALID: + case STATUS_INVALID_VARIANT: + case STATUS_POWER_STATE_INVALID: + case STATUS_INVALID_DEVICE_OBJECT_PARAMETER: + case STATUS_INVALID_BLOCK_LENGTH: + retstat = -EINVAL; + break; +#ifdef ENOMEDIUM + case STATUS_NO_MEDIA_IN_DEVICE: + case STATUS_UNRECOGNIZED_MEDIA: + retstat = -ENOMEDIUM; + break; +#endif + case STATUS_SHARING_VIOLATION: + case STATUS_FILE_LOCK_CONFLICT: + case STATUS_LOCK_NOT_GRANTED: + case STATUS_SHARING_PAUSED: + case STATUS_SHARED_POLICY: + case STATUS_NOT_LOCKED: + case STATUS_PIPE_BUSY: + case STATUS_CONNECTION_IN_USE: + case STATUS_WAIT_FOR_OPLOCK: + retstat = -EBUSY; + break; + case STATUS_LOGON_FAILURE: + case STATUS_ACCOUNT_RESTRICTION: + case STATUS_ILL_FORMED_PASSWORD: + case STATUS_PASSWORD_RESTRICTION: + case STATUS_INVALID_LOGON_HOURS: + case STATUS_INVALID_WORKSTATION: + case STATUS_PASSWORD_EXPIRED: + case STATUS_ACCOUNT_DISABLED: + case STATUS_WRONG_PASSWORD: + case STATUS_SECTION_PROTECTION: + case STATUS_PRIVILEGE_NOT_HELD: + case STATUS_PRIVILEGED_INSTRUCTION: + case STATUS_PASSWORD_MUST_CHANGE: + case STATUS_ACCOUNT_LOCKED_OUT: + case STATUS_RESOURCE_NOT_OWNED: + case STATUS_LICENSE_VIOLATION: + case STATUS_LICENSE_QUOTA_EXCEEDED: + case STATUS_EVALUATION_EXPIRATION: + case STATUS_COPY_PROTECTION_FAILURE: + case STATUS_SMARTCARD_WRONG_PIN: + case STATUS_SMARTCARD_CARD_BLOCKED: + case STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED: + case STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT: + case STATUS_ACCESS_DISABLED_BY_POLICY_PATH: + case STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER: + case STATUS_ACCESS_DISABLED_BY_POLICY_OTHER: + case STATUS_CSS_AUTHENTICATION_FAILURE: + case STATUS_CSS_KEY_NOT_PRESENT: + case STATUS_CSS_KEY_NOT_ESTABLISHED: + case STATUS_INSUFFICIENT_LOGON_INFO: + retstat = -EPERM; + break; + case STATUS_DEVICE_DOES_NOT_EXIST: + case STATUS_DEVICE_NOT_CONNECTED: + case STATUS_DEVICE_POWER_FAILURE: + case STATUS_DEVICE_REMOVED: + case STATUS_PLUGPLAY_NO_DEVICE: + case STATUS_VOLUME_DISMOUNTED: + case STATUS_NOINTERFACE: + case STATUS_PARTITION_FAILURE: + retstat = -ENODEV; + break; + case STATUS_NO_MORE_FILES: + case STATUS_OBJECT_NAME_NOT_FOUND: + case STATUS_NOT_FOUND: + case STATUS_INVALID_PLUGPLAY_DEVICE_PATH: + case STATUS_NO_SUCH_FILE: + case STATUS_NETWORK_NAME_DELETED: + case STATUS_FILE_IS_OFFLINE: + case STATUS_MOUNT_POINT_NOT_RESOLVED: + retstat = -ENOENT; + break; + case STATUS_LOGON_SESSION_EXISTS: + case STATUS_DUPLICATE_NAME: + case STATUS_ALIAS_EXISTS: + case STATUS_ADDRESS_ALREADY_EXISTS: + case STATUS_DUPLICATE_OBJECTID: + case STATUS_OBJECTID_EXISTS: + retstat = -EEXIST; + break; + case STATUS_WRONG_VOLUME: + retstat = -EXDEV; + break; + case STATUS_BUFFER_TOO_SMALL: + case STATUS_SECTION_TOO_BIG: + case STATUS_SYSTEM_HIVE_TOO_LARGE: + retstat = -E2BIG; + break; + case STATUS_MEMORY_NOT_ALLOCATED: + case STATUS_NO_MEMORY: + case STATUS_INSUFFICIENT_RESOURCES: + case STATUS_INSUFF_SERVER_RESOURCES: + retstat = -ENOMEM; + break; + case STATUS_INVALID_HANDLE: + case STATUS_FILE_INVALID: + case STATUS_INVALID_PORT_HANDLE: + case STATUS_FILE_DELETED: + case STATUS_FILE_CLOSED: + case STATUS_FILE_CORRUPT_ERROR: + case STATUS_USER_MAPPED_FILE: + case STATUS_NOT_A_REPARSE_POINT: + case STATUS_DIRECTORY_IS_A_REPARSE_POINT: + case STATUS_FILE_NOT_ENCRYPTED: + case STATUS_FILE_ENCRYPTED: + case STATUS_CORRUPT_SYSTEM_FILE: + case STATUS_HANDLE_NOT_CLOSABLE: + retstat = -EBADF; + break; + case STATUS_FILES_OPEN: + retstat = -EMFILE; + break; + case STATUS_TOO_MANY_OPENED_FILES: + retstat = -ENFILE; + break; + case STATUS_PIPE_NOT_AVAILABLE: + case STATUS_INVALID_PIPE_STATE: + case STATUS_PIPE_BROKEN: + case STATUS_PIPE_EMPTY: + retstat = -EPIPE; + break; + case STATUS_DISK_FULL: + case STATUS_NO_LOG_SPACE: + case STATUS_LOG_FILE_FULL: + case STATUS_NO_SPOOL_SPACE: + case STATUS_PRINT_QUEUE_FULL: + case STATUS_DESTINATION_ELEMENT_FULL: + retstat = -ENOSPC; + break; + case STATUS_MEDIA_WRITE_PROTECTED: + retstat = -EROFS; + break; + case STATUS_DIRECTORY_NOT_EMPTY: + retstat = -ENOTEMPTY; + break; + case STATUS_RETRY: + retstat = -EAGAIN; + break; + case STATUS_OBJECT_PATH_NOT_FOUND: + case STATUS_NOT_A_DIRECTORY: + retstat = -ENOTDIR; + break; + case STATUS_FILE_IS_A_DIRECTORY: + retstat = -EISDIR; + break; + case STATUS_UNEXPECTED_IO_ERROR: + case STATUS_IO_PRIVILEGE_FAILED: + case STATUS_DEVICE_NOT_READY: + case STATUS_IO_DEVICE_ERROR: + case STATUS_OPEN_FAILED: + case STATUS_REPLY_MESSAGE_MISMATCH: + case STATUS_LOST_WRITEBEHIND_DATA: + retstat = -EIO; + break; + case STATUS_NOT_SUPPORTED: + case STATUS_ILLEGAL_FUNCTION: + case STATUS_WMI_NOT_SUPPORTED: + retstat = -EOPNOTSUPP; + break; + case STATUS_PIPE_DISCONNECTED: + case STATUS_CONNECTION_ABORTED: + case STATUS_CONNECTION_DISCONNECTED: + case STATUS_CONNECTION_RESET: + retstat = -ECONNRESET; + break; + default: + break; + } + + return retstat; +} + +void * rdp_addport(void * inarg) { + callback * cbdata = (callback *)inarg; + int len = 0; + tbus fd = 0; + rdpport_t * port = (rdpport_t *)NULL; + struct cn_msg * data = (struct cn_msg *)NULL; + //rdp_socket_msg * rdpmsg = (rdp_socket_msg *)NULL; + void * rdata = (void *)NULL; + struct rdp_irq_data * rirq = (struct rdp_irq_data *)NULL; + unsigned char tbuf[512]; + + MDBGLOG("port","INFO\t[%s()]: called (inarg = 0x%p)", __func__, inarg); + + g_memset(tbuf, 0x00, sizeof(tbuf)); + fd = (cbdata != NULL && cbdata->port != NULL) ? cbdata->port->fd : -1; + if (fd < 0) { + MDBGLOG("port","ERROR\t[%s()]: fd = %d",__func__,fd); + goto end; + } + + port = cbdata->port; + + end:; + MDBGLOG("port","INFO\t[%s()]: done.", __func__); +} + +static void * rdp_irq_callback(void * inarg) { + callback * cbdata = (callback *)inarg; + int rv = 0; + int len = 0; + int olen = 0; + int reqid = 0; + int uniqid = 0; + int size = 0; + int fhandle = 0; + int qsize = 0; + int cid = 0; + tbus fd = 0; + tc_p lmutex = 0; + int rdpport_opcode = 0x00000000; + unsigned char * odata = (unsigned char *)NULL; + unsigned char * tp = (unsigned char *)NULL; + uint32_t crc32 = 0; + const uint32_t magic = RDP_PACKET_MAGIC; + uint32_t device_id = 0; + uint32_t * p_crc32 = (uint32_t *)NULL; + char * p = (char *)p; + rdpport_t * port = (rdpport_t *)NULL; + struct cn_msg * data = (struct cn_msg *)NULL; + //rdp_socket_msg * rdpmsg = (rdp_socket_msg *)NULL; + void * rdata = (void *)NULL; + struct rdp_irq_data * rirq = (struct rdp_irq_data *)NULL; + unsigned char tbuf[512]; + + MDBGLOG("port","INFO\t[%s()]: called",__func__); + + g_memset(tbuf, 0, sizeof(tbuf)); + fd = (cbdata != NULL && cbdata->port != NULL) ? cbdata->port->fd : -1; + if (fd < 0) { + MDBGLOG("port","ERROR\t[%s()]: fd = %d",__func__,fd); + rv = -EINVAL; + goto end; + } + + if (g_stop) { + goto end; + } + + port = cbdata->port; + reqid = cbdata->opid; + uniqid = cbdata->uniqid; + fhandle = cbdata->FileId; + cid = cbdata->CompletionId; + + qsize = 1; + MDBGLOG("port","INFO\t[%s()]: qsize = %d", __func__, qsize); + + get_mutex_port(reqid, &lmutex); + + if (qsize > 0) { + struct trans * lpcon = (struct trans *)NULL; + tc_p llmutex = (tc_p)NULL; + tc_p llcv = (tc_p)NULL; + uint32_t lreqid = 0x00000000; + uint32_t luniqid = 0x00000000; + uint32_t obuflen = 0x00000000; + uint64_t offset = 0x0000000000000000; + BYTE * obuf = (BYTE *)NULL; + LOCAL_STREAM(s); + + rdpport_opcode = RDPPORT_READ; + size = 0; + lreqid = reqid; + llmutex = lmutex; + luniqid = lreqid; + TC_MUTEX_LOCK((tc_p)llmutex); + + get_cv_port(lreqid, &llcv); + cbdata = &(g_reqids[lreqid]); + obuflen = sizeof(char) * qsize; + obuf = (BYTE *)g_malloc(cbdata->length + 1, 1); + cbdata->length = obuflen; + cbdata->userdata = (void *)obuf; + cbdata->flags = CBFLAG_PORT | CBFLAG_MUTEX | CBFLAG_FINAL; + cbdata->opid = lreqid; + cbdata->CompletionId = luniqid; + cbdata->uniqid = luniqid; + cbdata->port = port; + cbdata->FileId = fhandle; + cbdata->opcode = rdpport_opcode; + cbdata->trans = port->ccon; + cbdata->port = port; + + MDBGLOG("port","INFO\t[%s()]: &(cbdata->mutex) = \"%p\"; llmutex = \"%p\"", __func__, &(cbdata->mutex), (void *)llmutex); + MDBGLOG("port","INFO\t[%s()]: &(cbdata->cv) = \"%p\"; llcv = \"%p\"", __func__, &(cbdata->cv), (void *)llcv); + + TC_MUTEX_LOCK((tc_p)mutex_pcon_port); + lpcon = port->ccon; + lpcon->callback_data = cbdata; + s = trans_get_out_s(lpcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpport_opcode); + out_uint32_le(s, (size + sizeof(obuflen) + sizeof(offset))); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, luniqid); + p_crc32 = s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + out_uint32_le(s, obuflen); + out_uint64_le(s, offset); + s_mark_end(s); + size = s->end - s->data; + if ((s->end - p) > 0) { + *p_crc32 = Crc32_ComputeBuf((uint32_t)0, (void *)p, (size_t)(s->end - p)); + } + + MDBGLOG("port"," ** %s (read): sending [g_fd = %d, fhandle = %d, lreqid = %d, cbdata->CompletionId = %d, cbdata->uniqid = %d, cbdata->opid = %d]", __func__, g_fd, fhandle, lreqid, cbdata->CompletionId, cbdata->uniqid, cbdata->opid); + trans_force_write(lpcon); + g_memset(s->data,0,MAX_STREAM); + TC_MUTEX_UNLOCK((tc_p)mutex_pcon_port); + MDBGLOG("port","sent."); + + MDBGLOG("port","INFO\t[%s()]: entering g_obj_wait loop:",__func__); + tc_cond_wait((tc_p)llcv, (tc_p)llmutex); + MDBGLOG("port","INFO\t[%s()]: exiting g_obj_wait loop.",__func__); + + olen = cbdata->length; + odata = (unsigned char *)(cbdata->userdata); + + TC_MUTEX_UNLOCK((tc_p)llmutex); + } + + MDBGLOG("port","INFO\t[%s()]: olen = %d; odata = \"%s\"",__func__,olen,odata); + + data = (struct cn_msg *)tbuf; + //rdpmsg = (rdp_socket_msg *)(data->data); + //rdata = (void *)(&(rdpmsg->data)); + rirq = rdata; + //data->id.idx = CN_TEST_IDX; + //data->id.val = CN_TEST_VAL; + //data->seq = 0; + //data->ack = 0; + //data->len = sizeof(rdp_socket_msg) + sizeof(struct rdp_irq_data) + olen; + //rdpmsg->len = sizeof(struct rdp_irq_data) + olen; + //rdpmsg->type = RDP_M_ASYNC | RDP_M_RXFULL; + rirq->device_id = cbdata->port->device_id; + rirq->rx_len = olen; + if (olen > 0 && odata != NULL) { + g_memcpy(rirq->rx_buf, odata, olen); + } + //len = socket_send(fd, data); + + if (!g_stop) { + struct trans * pcon = (struct trans *)NULL; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + uint32_t cmd = 0x00000000; + uint32_t ibuflen = 0x00000000; + uint32_t obuflen = 0x00000000; + uint32_t * mask = (uint32_t *)NULL; + BYTE * ibuf = (BYTE *)NULL; + BYTE * obuf = (BYTE *)NULL; + LOCAL_STREAM(s); + + fhandle = cbdata->FileId; + mask = (uint32_t *)g_malloc(sizeof(uint32_t), 1); + *mask = cbdata->mask; + + TC_MUTEX_LOCK((tc_p)mutex_portop); + get_reqid_port(&reqid); + get_mutex_port(reqid, &lmutex); + TC_MUTEX_LOCK((tc_p)lmutex); + TC_MUTEX_UNLOCK((tc_p)mutex_portop); + + cbdata = &(g_reqids[reqid]); + + rdpport_opcode = RDPPORT_IOCTL; + cmd = IOCTL_SERIAL_WAIT_ON_MASK; + ibuflen = 0; + ibuf = NULL; + obuflen = sizeof(ULONG); + size = 0; + uniqid = reqid; + + cbdata->call = &rdp_irq_callback; + cbdata->cmd = cmd; + cbdata->flags = CBFLAG_PORT | CBFLAG_IRQ | CBFLAG_MUTEX | CBFLAG_FUNC | CBFLAG_CMD | CBFLAG_MASK; + cbdata->opid = reqid; + cbdata->CompletionId = uniqid; + cbdata->uniqid = uniqid; + cbdata->port = port; + cbdata->FileId = fhandle; + cbdata->opcode = rdpport_opcode; + cbdata->mask = *mask; + + crc32 = 0; + + TC_MUTEX_LOCK((tc_p)mutex_pcon_port); + g_irq_cb = cbdata; + g_irq_idx = reqid; + pcon = port->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, magic); + out_uint32_le(s, rdpport_opcode); + out_uint32_le(s, size + (sizeof(cmd) + sizeof(ibuflen) + sizeof(obuflen) + ibuflen)); + out_uint32_le(s, device_id); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + p_crc32 = s_get_pos(s); + out_uint32_le(s, crc32); + p = (char *)s_get_pos(s); + out_uint32_le(s, cmd); + out_uint32_le(s, ibuflen); + out_uint32_le(s, obuflen); + s_mark_end(s); + size = s->end - s->data; + if ((s->end - p) > 0) { + *p_crc32 = Crc32_ComputeBuf(0, p, s->end - p); + } + + MDBGLOG("port"," ** %s (waitonmask): sending [g_fd = %d, fhandle = %d, reqid = %d, cbdata->CompletionId = %d, cbdata->uniqid = %d, cbdata->opid = %d, cbdata->cmd = 0x%8.8x]", __func__, g_fd, fhandle, reqid, cbdata->CompletionId, cbdata->uniqid, cbdata->opid, cbdata->cmd); + trans_force_write(pcon); + TC_MUTEX_UNLOCK((tc_p)lmutex); + g_memset(s->data,0,MAX_STREAM); + MDBGLOG("port","sent."); + TC_MUTEX_UNLOCK((tc_p)mutex_pcon_port); + goto end; + } + + cbdata->userdata = NULL; + TC_MUTEX_UNLOCK((tc_p)lmutex); + free_reqid_port(reqid); + + end:; + MDBGLOG("port", "INFO\t[%s()]: done.", __func__); + tc_thread_exit(NULL); +} diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/rdpport_defs.h posixrdp/posixxrdp.orig/sesman/chansrv/rdpport_defs.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/rdpport_defs.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/rdpport_defs.h 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,8 @@ +#ifndef XRDPPORT_DEFS +#define XRDPPORT_DEFS + +static const char * cmdarray[] = CMD_TO_STRING_ARRAY_DEF; + +#define RDPUARTCMD(x) (cmdarray[(x & 0x1f)]) + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/rdpprint.c posixrdp/posixxrdp.orig/sesman/chansrv/rdpprint.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/rdpprint.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/rdpprint.c 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,1477 @@ +/* + * + * Client-side printer redirection over RDP + * + */ + +#include "params.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" +#include "arch.h" +#include "parse.h" +#include "defines.h" +#include "rdpdr.h" +#include "rdpdr_methods.h" +#include "trans.h" +#include "devredir_defs.h" +#include "global.h" +#include "thread_calls.h" +#include "dbg.h" + +static int g_fd = -1; +static rdpprint * g_printer = (rdpprint *)NULL; + +static uint32_t pmagic = RDP_PACKET_MAGIC; + +#ifndef MAX_REQID +#define MAX_REQID 25 +#endif +static callback g_reqids[MAX_REQID]; + +#ifndef MAX_MUTEX +#define MAX_MUTEX 25 +#endif +static tbus g_mutexes[MAX_MUTEX]; +static pthread_cond_t g_condition_variables[MAX_MUTEX]; + +//tbus mutex_device; +extern tc_p g_mutex; +extern tc_p mut; + +static tc_t g_mutex_pcon; +static tc_t g_mutex_print; +static tc_t g_mutex_device; +static tc_t g_mutex_parent; +static tc_t g_mutex_printop; +static tc_t g_mutex_reqid; +static tc_p mutex_pcon = (tc_p)NULL; +static tc_p mutex_print = (tc_p)NULL; +static tc_p mutex_parent = (tc_p)NULL; +static tc_p mutex_printop = (tc_p)NULL; +static tc_p mutex_reqid = (tc_p)NULL; +static tc_p mutex_device = (tc_p)NULL; + +static int APP_CC rdpprint_open(tbus); +static int APP_CC rdpprint_open_args(tbus, uint32_t, uint32_t, uint32_t, uint32_t); +static int APP_CC rdpprint_release(tbus); +static int APP_CC rdpprint_ioctl(tbus, int, size_t, void *, size_t, void *); + +static int APP_CC rdpprint_cycle(rdpprint *); + +static int APP_CC get_reqid(int *); +static int APP_CC free_reqid(int); +static int APP_CC init_reqids(void); +static int APP_CC get_mutex(int, tc_p); +static int APP_CC get_cv(int, tc_p); +static int APP_CC ntstatus_to_errcode(DWORD); + +extern int APP_CC get_RDPDR_HEADER(RDPDR_HEADER *, struct stream *); +extern int APP_CC get_DR_DEVICE_IOCOMPLETION(DR_DEVICE_IOCOMPLETION *, struct stream *); +extern int APP_CC get_DR_CREATE_RSP(DR_CREATE_RSP *, struct stream *); +extern int APP_CC get_DR_DRIVE_QUERY_INFORMATION_RSP(DR_DRIVE_QUERY_INFORMATION_RSP *, struct stream *); +extern int APP_CC get_DR_DRIVE_CREATE_RSP(DR_DRIVE_CREATE_RSP *, struct stream *); +extern int APP_CC construct_RDPDR_HEADER(RDPDR_HEADER *); +extern int APP_CC construct_DR_DEVICE_IOCOMPLETION(DR_DEVICE_IOCOMPLETION *); +extern int APP_CC construct_DR_CREATE_RSP(DR_CREATE_RSP *); +extern int APP_CC construct_DR_DRIVE_CREATE_RSP(DR_DRIVE_CREATE_RSP *); +extern char * APP_CC ntstatus_string(uint32_t); + +static int APP_CC parent_data_in(struct trans *); + +/* + * printer open operation + */ +static int rdpprint_open(tbus fh) { + int retstat = 0; + struct stream * s = NULL; + int idx = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpprint_opcode = 0x00000000; + int size = 0x00000000; + rdpprint_data rdata; + tbus lmutex = (tbus)NULL; + tbus lcv = (tbus)NULL; + callback * cbdata = NULL; + uint32_t pflags = 0x00000000; + uint32_t pshare = 0x00000000; + uint32_t poptions = 0x00000000; + uint32_t pattributes = 0x00000000; + int reqid = -1; + int uniqid = 0; + uint32_t magic = 0; + uint32_t crc32 = 0; + uint32_t calc_crc32 = 0; + + MDBGLOG("print","\n\nrdpprint_open (fh=\"%d\")\n",fh); + + g_memset(&rdata,0,sizeof(rdpprint_data)); + + tc_mutex_lock(mutex_printop); + get_reqid(&reqid); + get_mutex(reqid, &lmutex); + tc_mutex_lock(lmutex); + tc_mutex_unlock(mutex_printop); + + get_cv(reqid, &lcv); + cbdata = &(g_reqids[reqid]); + + pflags = GENERIC_ALL; + pshare |= (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE); + + rdpprint_opcode = RDPPRINT_OPEN; + uniqid = reqid; + + tc_mutex_lock(mutex_pcon); + pcon = g_printer->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, pmagic); + out_uint32_le(s, rdpprint_opcode); + out_uint32_le(s, size + 16); + out_uint32_le(s, fh); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + out_uint32_le(s, pflags); + out_uint32_le(s, pshare); + out_uint32_le(s, poptions); + out_uint32_le(s, pattributes); + s_mark_end(s); + size = s->end - s->data; + + g_hexdump_file("/tmp/taskq_print_open.hexdump", s->data, size); + MDBGLOG("print"," ** rdpprint_open(): sending [g_fd = %d]", g_fd); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + DBGLOG("print","sent."); + tc_mutex_unlock(mutex_pcon); + + DBGLOG("print","entering g_obj_wait loop:"); + tc_cond_wait(lcv, lmutex); + DBGLOG("print","exiting g_obj_wait loop."); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("print","ERROR [rdpprint_open()]: \"%s\" (retstat = %d; cbdata->IoStatus.Fields.Sev = 0x%8.8x)",nterr,retstat,cbdata->IoStatus.Value); + } + + MDBGLOG("print","rdpprint_open(): done. (fh = %d; retstat = %d)",fh,retstat); + + tc_mutex_unlock(lmutex); + free_reqid(reqid); + + return retstat; +} + +static int rdpprint_open_args(tbus fh, uint32_t pflags, uint32_t pshare, uint32_t poptions, uint32_t pattributes) { + int retstat = 0; + struct stream * s = NULL; + int idx = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpprint_opcode = 0x00000000; + int size = 0x00000000; + rdpprint_data rdata; + tbus lmutex = (tbus)NULL; + tbus lcv = (tbus)NULL; + callback * cbdata = NULL; + int reqid = -1; + int fhandle = 0; + int uniqid = 0; + uint32_t magic = 0; + uint32_t crc32 = 0; + uint32_t calc_crc32 = 0; + + MDBGLOG("print","\n\nrdpprint_open_args (fh = \"%d\"; pflags = 0x%8.8x; pshare = 0x%8.8x; poptions = 0x%8.8x)\n",fh,pflags,pshare,poptions); + + g_memset(&rdata,0,sizeof(rdpprint_data)); + + tc_mutex_lock(mutex_printop); + get_reqid(&reqid); + get_mutex(reqid, &lmutex); + tc_mutex_lock(lmutex); + tc_mutex_unlock(mutex_printop); + + get_cv(reqid, &lcv); + cbdata = &(g_reqids[reqid]); + + rdpprint_opcode = RDPPRINT_OPEN; + uniqid = reqid; + + tc_mutex_lock(mutex_pcon); + pcon = g_printer->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, pmagic); + out_uint32_le(s, rdpprint_opcode); + out_uint32_le(s, size + 16); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + out_uint32_le(s, pflags); + out_uint32_le(s, pshare); + out_uint32_le(s, poptions); + out_uint32_le(s, pattributes); + s_mark_end(s); + size = s->end - s->data; + + g_hexdump_file("/tmp/taskq_print_open_args.hexdump", s->data, size); + MDBGLOG("print"," ** rdpprint_open_args(): sending [g_fd = %d]", g_fd); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + DBGLOG("print","sent."); + tc_mutex_unlock(mutex_pcon); + + DBGLOG("print","entering g_obj_wait loop:"); + tc_cond_wait(lcv, lmutex); + DBGLOG("print","exiting g_obj_wait loop."); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("print","ERROR [rdpprint_open_args()]: \"%s\" (retstat = %d; cbdata->IoStatus.Fields.Sev = 0x%8.8x)",nterr,retstat,cbdata->IoStatus.Value); + fhandle = -1; + } + + MDBGLOG("print","rdpprint_open_args(): done. (fh = %d; retstat = %d)",fh,retstat); + + tc_mutex_unlock(lmutex); + free_reqid(reqid); + + return retstat; +} + +/** Read data from an open file + * + * Read should return exactly the number of bytes requested except + * on EOF or error, otherwise the rest of the data will be + * substituted with zeroes. An exception to this is when the + * 'direct_io' mount option is specified, in which case the return + * value of the read system call will reflect the return value of + * this operation. + * + * Changed in version 2.2 + */ +// I don't fully understand the documentation above -- it doesn't +// match the documentation for the read() system call which says it +// can return with anything up to the amount of data requested. nor +// with the fusexmp code which returns the amount of data also +// returned by read. + +static int rdpprint_read_chunk(tbus fh, char * buf, size_t size) { + int retstat = 0; + int plen = 0; + struct stream * s = NULL; + int idx = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpprint_opcode = 0x00000000; + int reqid = -1; + int uniqid = 0; + tbus lmutex = (tbus)NULL; + tbus lcv = (tbus)NULL; + callback * cbdata = NULL; + int mode = 0; + size_t fsize = 0; + uint32_t magic = 0; + uint32_t crc32 = 0; + uint32_t calc_crc32 = 0; + + tc_mutex_lock(mutex_printop); + get_reqid(&reqid); + get_mutex(reqid, &lmutex); + tc_mutex_lock(lmutex); + tc_mutex_unlock(mutex_printop); + + cbdata = &(g_reqids[reqid]); + cbdata->userdata = buf; + + rdpprint_opcode = RDPPRINT_READ; + uniqid = reqid; + + tc_mutex_lock(mutex_pcon); + pcon = g_printer->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, pmagic); + out_uint32_le(s, rdpprint_opcode); + out_uint32_le(s, 4); + out_uint32_le(s, fh); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + out_uint32_le(s, size); + s_mark_end(s); + fsize = s->end - s->data; + g_hexdump_file("/tmp/taskq_print_read_chunk_cmd.hexdump", s->data, fsize); + trans_force_write(pcon); + g_memset(s->data,0,sizeof(char)*MAX_STREAM); + tc_mutex_unlock(mutex_pcon); + DBGLOG("print","sent."); + + DBGLOG("print"," Entering wait loop..."); + get_cv(reqid,&lcv); + tc_cond_wait(lcv,lmutex); + DBGLOG("print"," Finished."); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + const char * nterr = (const char *)ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("print","ERROR [rdpprint_read_chunk()]: \"%s\" (retstat = %d; cbdata->IoStatus.Value = 0x%8.8x)",nterr,retstat,cbdata->IoStatus.Value); + //retstat = 0; + } + else { + retstat = cbdata->length; + } + g_hexdump_file("/tmp/taskq_print_read_chunk_result.hexdump", cbdata->userdata, cbdata->length); + g_memset(cbdata,0,sizeof(callback)); + + tc_mutex_unlock(lmutex); + free_reqid(reqid); + + return retstat; +} + +static int rdpprint_read(tbus fh, char * buf, size_t size) { + #ifndef CHUNK_SIZE + #define CHUNK_SIZE 4096 + #endif + int retstat = 0; + struct stream * s = NULL; + int idx = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpprint_opcode = 0x00000000; + int reqid = -1; + int uniqid = 0; + tbus lmutex = (tbus)NULL; + tbus lcv = (tbus)NULL; + callback * cbdata = NULL; + int mode = 0; + int chunks = 0; + char * tpos = NULL; + off_t toffset = 0; + size_t tsize = 0; + uint64_t tally = 0; + + MDBGLOG("print","rdpprint_read(): fh = %d; size = %d",fh,size); + + chunks = (size == 0) ? 0 : 1; + if (size > CHUNK_SIZE) { + chunks = ((size % CHUNK_SIZE) == 0) ? size / CHUNK_SIZE : (size / CHUNK_SIZE) + 1; + } + + for (idx = 0; idx < chunks; idx++) { + tpos = buf + (idx * CHUNK_SIZE); + toffset = 0; + tsize = (idx == (chunks - 1) && (size % CHUNK_SIZE) != 0) ? size % CHUNK_SIZE : CHUNK_SIZE; + retstat = rdpprint_read_chunk(fh,tpos,tsize); + if (retstat < 0) { + break; + } + else { + tally += retstat; + } + } + if (retstat > -1) { + retstat = tally; + } + + return retstat; +} + +/** Write data to an open file + * + * Write should return exactly the number of bytes requested + * except on error. An exception to this is when the 'direct_io' + * mount option is specified (see read operation). + * + * Changed in version 2.2 + */ +static int rdpprint_write_chunk(tbus fh, const char * buf, size_t size) { + int retstat = 0; + struct stream * s = NULL; + int idx = 0; + int fsize = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpprint_opcode = 0x00000000; + int reqid = -1; + int uniqid = 0; + tbus lmutex = (tbus)NULL; + tbus lcv = (tbus)NULL; + callback * cbdata = NULL; + uint32_t magic = 0; + uint32_t crc32 = 0; + uint32_t calc_crc32 = 0; + + tc_mutex_lock(mutex_printop); + get_reqid(&reqid); + get_mutex(reqid, &lmutex); + tc_mutex_lock(lmutex); + tc_mutex_unlock(mutex_printop); + + cbdata = &(g_reqids[reqid]); + cbdata->userdata = (char *)buf; + + rdpprint_opcode = RDPPRINT_WRITE; + uniqid = reqid; + + tc_mutex_lock(mutex_pcon); + pcon = g_printer->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, pmagic); + out_uint32_le(s, rdpprint_opcode); + out_uint32_le(s, size); + out_uint32_le(s, fh); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + if (size > 0) { + out_uint8a(s, buf, size); + } + s_mark_end(s); + fsize = s->end - s->data; + g_hexdump_file("/tmp/taskq_print_write_chunk_cmd.hexdump", s->data, fsize); + trans_force_write(pcon); + g_memset(s->data,0,sizeof(char)*MAX_STREAM); + tc_mutex_unlock(mutex_pcon); + DBGLOG("print","sent."); + + DBGLOG("print"," Entering wait loop..."); + get_cv(reqid,&lcv); + tc_cond_wait(lcv,lmutex); + DBGLOG("print"," Finished."); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + MDBGLOG("print","ERROR [rdpprint_write_chunk()]: retstat = %d; cbdata->IoStatus.Value = %d",retstat,cbdata->IoStatus.Value); + } + else { + retstat = cbdata->length; + } + g_hexdump_file("/tmp/taskq_print_write_chunk_result.hexdump", cbdata->userdata, cbdata->length); + g_memset(cbdata,0,sizeof(callback)); + + tc_mutex_unlock(lmutex); + free_reqid(reqid); + + return retstat; +} + +static int rdpprint_write(tbus fh, const char * buf, size_t size) { + #ifndef CHUNK_SIZE + #define CHUNK_SIZE 4096 + #endif + int retstat = 0; + struct stream * s = NULL; + int idx = 0; + int fsize = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpprint_opcode = 0x00000000; + int reqid = -1; + int uniqid = 0; + tbus lmutex = (tbus)NULL; + tbus lcv = (tbus)NULL; + callback * cbdata = NULL; + int mode = 0; + int chunks = 0; + char * tpos = (BYTE *)NULL; + off_t toffset = 0; + size_t tsize = 0; + uint64_t tally = 0; + + chunks = (size == 0) ? 0 : 1; + if (size > CHUNK_SIZE) { + chunks = ((size % CHUNK_SIZE) == 0) ? size / CHUNK_SIZE : (size / CHUNK_SIZE) + 1; + } + + for (idx = 0; idx < chunks; idx++) { + tpos = (char *)buf + (idx * CHUNK_SIZE); + tsize = (idx == (chunks - 1) && (size % CHUNK_SIZE) != 0) ? size % CHUNK_SIZE : CHUNK_SIZE; + retstat = rdpprint_write_chunk(fh,tpos,tsize); + if (retstat < 0) { + break; + } + else { + tally += retstat; + } + } + if (retstat > -1) { + retstat = tally; + } + + return retstat; +} + +/** Release an open file + * + */ +static int rdpprint_release(tbus fh) { + int retstat = 0; + struct stream * s = NULL; + int idx = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpprint_opcode = 0x00000000; + int size = 0x00000000; + rdpprint_data rdata; + int uniqid = 0; + int reqid = -1; + callback * cbdata = NULL; + tbus lmut = (tbus)NULL; + tbus lcv = (tbus)NULL; + uint32_t magic = 0; + uint32_t crc32 = 0; + uint32_t calc_crc32 = 0; + + tc_mutex_lock(mutex_printop); + get_reqid(&reqid); + get_mutex(reqid,&lmut); + tc_mutex_lock(lmut); + tc_mutex_unlock(mutex_printop); + + MDBGLOG("print","\n\nrdpprint_release(fh=\"%d\")\n",fh); + g_memset(&rdata,0,sizeof(rdpprint_data)); + + rdpprint_opcode = RDPPRINT_CLOSE; + uniqid = reqid; + cbdata = &(g_reqids[reqid]); + cbdata->FileId = fh; + + tc_mutex_lock(mutex_pcon); + pcon = g_printer->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, pmagic); + out_uint32_le(s, rdpprint_opcode); + out_uint32_le(s, size); + out_uint32_le(s, fh); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + s_mark_end(s); + size = s->end - s->data; + MDBGLOG("print"," ** rdpprint_release(): sending [g_fd = %d]", g_fd); + trans_force_write(pcon); + DBGLOG("print","sent."); + g_hexdump_file("/tmp/taskq_print_release.hexdump", s->data, size); + g_memset(s->data,0,MAX_STREAM); + tc_mutex_unlock(mutex_pcon); + + get_cv(reqid,&lcv); + DBGLOG("print"," Waiting..."); + tc_cond_wait(lcv,lmut); + DBGLOG("print"," Done."); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + //retstat = rdpprint_error("rdpprint_release lstat"); + MDBGLOG("print","ERROR [rdpprint_release()]: \"%s\" (retstat = %d)",nterr,retstat); + } + + MDBGLOG("print","rdpprint_release(): done. ()"); + + tc_mutex_unlock(lmut); + free_reqid(reqid); + + return retstat; +} + +/* + * + * Ioctl + * + */ +static int rdpprint_ioctl(tbus fh, int cmd, size_t argslen, void * args, size_t buflen, void * buf) { + int retstat = 0; + struct stream * s = NULL; + struct trans * pcon = (struct trans *)NULL; + int rdpprint_opcode = 0x00000000; + int size = 0x00000000; + rdpprint_data rdata; + tbus lmutex = (tbus)NULL; + tbus lcv = (tbus)NULL; + callback * cbdata = NULL; + int reqid = -1; + int uniqid = 0; + uint32_t magic = 0; + uint32_t crc32 = 0; + uint32_t calc_crc32 = 0; + + tc_mutex_lock(mutex_printop); + get_reqid(&reqid); + get_mutex(reqid, &lmutex); + tc_mutex_lock(lmutex); + tc_mutex_unlock(mutex_printop); + + MDBGLOG("print","\n\nrdpprint_ioctl (fh=\"%d\"; argslen=\"%d\"; buflen=\"%d\")\n",fh,argslen,buflen); + + g_memset(&rdata,0,sizeof(rdpprint_data)); + + get_cv(reqid, &lcv); + cbdata = &(g_reqids[reqid]); + + rdpprint_opcode = RDPPRINT_IOCTL; + uniqid = reqid; + size = argslen; + + tc_mutex_lock(mutex_pcon); + pcon = g_printer->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, pmagic); + out_uint32_le(s, rdpprint_opcode); + out_uint32_le(s, size + 4); + out_uint32_le(s, fh); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + out_uint32_le(s, cmd); + if (argslen > 0) { + out_uint8a(s, (char *)args, argslen); + } + s_mark_end(s); + size = s->end - s->data; + + g_hexdump_file("/tmp/taskq_print_ioctl.hexdump", s->data, size); + MDBGLOG("print"," ** rdpprint_ioctl(): sending [g_fd = %d; fh = %d; size = %d]", g_fd, argslen, size); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + DBGLOG("print","sent."); + tc_mutex_unlock(mutex_pcon); + + DBGLOG("print","entering g_obj_wait loop:"); + tc_cond_wait(lcv, lmutex); + DBGLOG("print","exiting g_obj_wait loop."); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("print","ERROR [rdpprint_ioctl()]: \"%s\" (cbdata->IoStatus.Fields.Sev == STATUS_SEVERITY_ERROR)",nterr); + } + + DBGLOG("print","rdpprint_ioctl(): done."); + + tc_mutex_unlock(lmutex); + free_reqid(reqid); + + return retstat; +} + + +/*****************************************************************************/ +/***** child process-related section ******/ +/*****************************************************************************/ + + +/*****************************************************************************/ +static int APP_CC +parent_data_in(struct trans * trans) { + struct stream * s = (struct stream *)NULL; + int rdpprint_opcode = 0; + int rdpprint_reply = 0; + int size = 0; + int error = 0; + int fault = 0; + int fhandle = 0; + int uniqid = 0; + int fdone = 0; + BYTE buf[MAX_STREAM]; + uint32_t magic = 0; + uint32_t crc32 = 0; + uint32_t calc_crc32 = 0; + + DBGLOG("print","parent_data_in(): called"); + + g_memset((BYTE *)buf,0,sizeof(BYTE)*MAX_STREAM); + + if (trans == 0) + { + return 0; + } + tc_mutex_lock(mutex_pcon); + s = (struct stream *)trans_get_in_s(trans); + in_uint32_le(s, magic); + in_uint32_le(s, rdpprint_reply); + in_uint32_le(s, size); + in_uint32_le(s, fhandle); + in_uint32_le(s, uniqid); + in_uint32_le(s, crc32); + if (size > 0) { + error = trans_force_read(trans, size); + } + if (error == 0) + { + /* the entire message block has been read in, so process it: */ + fault = ((rdpprint_reply & RDPPRINT_ERROR) == 0) ? 0 : 1; + rdpprint_opcode = rdpprint_reply & (~(RDPPRINT_REPLY | RDPPRINT_ERROR)); + MDBGLOG("print"," ** parent_data_in(): rdpprint_opcode = 0x%8.8x; rdpprint_reply = 0x%8.8x; fault = %d; uniqid = %d",rdpprint_opcode,rdpprint_reply,fault,uniqid); + if (fault > 0) { + NTSTATUS iostatus = { .Value = 0x00000000 }; + int reqid = -1; + callback * cbdata = NULL; + tbus lmut = (tbus)NULL; + tbus lcv = (tbus)NULL; + char * nterr = (char *)NULL; + + tc_mutex_lock(mutex_printop); + in_uint32_le(s, iostatus.Value); + + nterr = ntstatus_string(iostatus.Value); + MDBGLOG("print"," --> FAULT: \"%s\" (status = 0x%8.8x)",nterr,iostatus.Value); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + if (reqid > -1) { + get_mutex(reqid, &lmut); + tc_mutex_lock(lmut); + tc_mutex_unlock(mutex_printop); + cbdata->IoStatus.Value = iostatus.Value; + get_cv(reqid, &lcv); + tc_cond_signal(lcv); + } + else { + lmut = mutex_printop; + } + tc_mutex_unlock(lmut); + } + else switch(rdpprint_opcode) { + case RDPPRINT_OPEN: + DBGLOG("print"," ^^ (RDPPRINT_OPEN)"); + { + DR_DRIVE_CREATE_RSP iorsp; + int reqid = -1; + callback * cbdata = NULL; + tbus lmut = (tbus)NULL; + tbus lcv = (tbus)NULL; + tc_mutex_lock(mutex_printop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex(reqid, &lmut); + tc_mutex_lock(lmut); + tc_mutex_unlock(mutex_printop); + get_cv(reqid, &lcv); + construct_DR_DRIVE_CREATE_RSP(&iorsp); + if (size > 0 && size < MAX_STREAM) { + get_DR_DRIVE_CREATE_RSP(&iorsp, s); + } + cbdata->FileId = iorsp.DeviceCreateResponse.FileId; + MDBGLOG("print"," --> FileId = %d; fhandle = %d",cbdata->FileId,fhandle); + { + int tsize = 0; + char vdata[MAX_STREAM]; + struct stream vs; + struct stream * v = &vs; + g_memset(&vdata,0,sizeof(char)*MAX_STREAM); + g_memset(v,0,sizeof(struct stream)); + v->data = (char *)(&vdata); + v->p = v->data; + v->end = v->data; + v->size = MAX_STREAM; + send_DR_DRIVE_CREATE_RSP(&iorsp, v); + s_mark_end(v); + tsize = v->end - v->data; + g_hexdump_file("/tmp/taskq_print_open_reply.hexdump",v->data,tsize); + } + tc_cond_signal(lcv); + tc_mutex_unlock(lmut); + } + break; + case RDPPRINT_READ: + DBGLOG("print"," ^^ (RDPPRINT_READ)"); + { + DR_DRIVE_READ_RSP iorsp; + int reqid = -1; + callback * cbdata = (callback *)NULL; + tbus lmut = (tbus)NULL; + tbus lcv = (tbus)NULL; + tc_mutex_lock(mutex_printop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex(reqid, &lmut); + tc_mutex_lock(lmut); + tc_mutex_unlock(mutex_printop); + construct_DR_READ_RSP(&iorsp); + iorsp.ReadData = cbdata->userdata; + get_DR_READ_RSP(&iorsp, s); + cbdata->length = iorsp.Length; + get_cv(reqid,&lcv); + tc_cond_signal(lcv); + tc_mutex_unlock(lmut); + MDBGLOG("print"," ^^ (RDPPRINT_READ): iorsp.Length = %d; iorsp.ReadData = \"%s\"",iorsp.Length,iorsp.ReadData); + } + break; + case RDPPRINT_WRITE: + DBGLOG("print"," ^^ (RDPPRINT_WRITE)"); + { + DR_DRIVE_WRITE_RSP iorsp; + int reqid = -1; + callback * cbdata = (callback *)NULL; + tbus lmut = (tbus)NULL; + tbus lcv = (tbus)NULL; + tc_mutex_lock(mutex_printop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex(reqid, &lmut); + tc_mutex_lock(lmut); + tc_mutex_unlock(mutex_printop); + construct_DR_WRITE_RSP(&iorsp); + get_DR_WRITE_RSP(&iorsp, s); + cbdata->length = iorsp.Length; + get_cv(reqid,&lcv); + tc_cond_signal(lcv); + tc_mutex_unlock(lmut); + } + break; + case RDPPRINT_IOCTL: + DBGLOG("print"," ^^ (RDPPRINT_IOCTL)"); + { + DR_CONTROL_RSP iorsp; + int reqid = -1; + callback * cbdata = (callback *)NULL; + tbus lmut = (tbus)NULL; + tbus lcv = (tbus)NULL; + tc_mutex_lock(mutex_printop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex(reqid, &lmut); + tc_mutex_lock(lmut); + tc_mutex_unlock(mutex_printop); + construct_DR_CONTROL_RSP(&iorsp); + iorsp.OutputBuffer = cbdata->userdata; + get_DR_CONTROL_RSP(&iorsp, s); + cbdata->length = iorsp.OutputBufferLength; + get_cv(reqid,&lcv); + tc_cond_signal(lcv); + tc_mutex_unlock(lmut); + MDBGLOG("print"," ^^ (RDPPRINT_IOCTL): iorsp.OutputBufferLength = %d;",iorsp.OutputBufferLength); + } + break; + case RDPPRINT_CLOSE: + DBGLOG("print"," ^^ (RDPPRINT_CLOSE)"); + { + int reqid = -1; + callback * cbdata = (callback *)NULL; + tbus lmut = (tbus)NULL; + tbus lcv = (tbus)NULL; + tc_mutex_lock(mutex_printop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex(reqid, &lmut); + tc_mutex_lock(lmut); + tc_mutex_unlock(mutex_printop); + get_cv(reqid,&lcv); + tc_cond_signal(lcv); + tc_mutex_unlock(lmut); + } + break; + case RDPPRINT_INIT: + DBGLOG("print"," ^^ (rdpprint_INIT)"); + { + int reqid = -1; + callback * cbdata = (callback *)NULL; + filelist * lst = (filelist *)NULL; + tbus lmut = (tbus)NULL; + tbus lcv = (tbus)NULL; + } + break; + case RDPPRINT_DESTROY: + DBGLOG("print"," ^^ (rdpprint_DESTROY)"); + exit(0); + break; + case RDPPRINT_ERROR: + DBGLOG("print"," ^^ (RDPPRINT_ERROR)"); + exit(0); + break; + } + } + tc_mutex_unlock(mutex_pcon); + return error; +} + +typedef struct _handle_printer_loop_args { + rdpprint * printer; + struct trans * pcon; + tbus objs[2]; + int num_objs; + int timeout; + int check_parent; + int check_device; +} handle_printer_loop_args; + +static void * APP_CC +loop_parent_print(void * inargs) { + handle_printer_loop_args * largs = (handle_printer_loop_args *)inargs; + rdpprint * printer = largs->printer; + struct trans * pcon = largs->pcon; + tbus * objs = (tbus *)(largs->objs); + int num_objs = largs->num_objs; + int timeout = largs->timeout; + int check_parent = largs->check_parent; + int check_device = largs->check_device; + if (inargs != NULL && objs != NULL && num_objs > 0 && check_parent > 0) { + /* handle any inbound communication from the parent process: */ + while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) { + if ((check_parent > 0) && g_is_wait_obj_set(objs[0])) { + tc_mutex_lock(mutex_parent); + if (trans_check_wait_objs(pcon) != 0) { + DBGLOG("print","ERROR [loop_parent_print()]: "); + //rv = -1; + break; + } + tc_mutex_unlock(mutex_parent); + } + } + } + tc_thread_exit(NULL); +} + +static void * APP_CC +loop_device_print(void * inargs) { + handle_printer_loop_args * largs = (handle_printer_loop_args *)inargs; + rdpprint * printer = largs->printer; + struct trans * pcon = largs->pcon; + tbus * objs = (tbus *)(largs->objs); + int num_objs = largs->num_objs; + int timeout = largs->timeout; + int check_parent = largs->check_parent; + int check_device = largs->check_device; + if (inargs != NULL && objs != NULL && num_objs > 0 && check_device > 0) { + /* handle communication from pseudo-device (i.e., the artificial serial or parallel printer on the server): */ + while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) { + if ((check_device > 0) && ((num_objs == 2 && g_is_wait_obj_set(objs[1])) || (num_objs == 1 && g_is_wait_obj_set(objs[0])))) { + tc_mutex_lock(mutex_device); + rdpprint_cycle(printer); + tc_mutex_unlock(mutex_device); + } + } + } + tc_thread_exit(NULL); +} + +/*****************************************************************************/ +static int APP_CC +rdpprint_cycle(rdpprint * printer) { + int rv = 0; + return rv; +} + +/*****************************************************************************/ +int APP_CC +handle_printer(tbus sck, rdpprint * printer) { + int rv = 0; + int brk = 0; + struct trans * pcon = (struct trans *)NULL; + tbus objs[2] = { -1, -1 }; + int num_objs = 0; + int timeout = 0; + int check_parent = 0; + int check_device = 0; + handle_printer_loop_args largs; + tbus thread_parent; + tbus thread_device; + + MDBGLOG("print","handle_printer(): sck = %d",sck); + g_memset(&largs,0,sizeof(handle_printer_loop_args)); + g_memset(&thread_parent,0,sizeof(tbus)); + g_memset(&thread_device,0,sizeof(tbus)); + + mut = (tc_p)&g_mutex; + mutex_pcon = (tc_p)&g_mutex_pcon; + mutex_print = (tc_p)&g_mutex_print; + mutex_printop = (tc_p)&g_mutex_printop; + mutex_parent = (tc_p)&g_mutex_parent; + mutex_device = (tc_p)&g_mutex_device; + mutex_reqid = (tc_p)&g_mutex_reqid; + tc_mutex_init(mut,NULL); + tc_mutex_init(mutex_pcon,NULL); + tc_mutex_init(mutex_print,NULL); + tc_mutex_init(mutex_printop,NULL); + tc_mutex_init(mutex_parent,NULL); + tc_mutex_init((tc_t *)mutex_device,NULL); + tc_mutex_init((tc_t *)mutex_reqid,NULL); + + tc_mutex_lock(mutex_pcon); + tc_mutex_lock(mutex_print); + + init_reqids(); + + /* set up pcon as a transmission channel to the parent */ + pcon = (struct trans *)trans_create((int)2, (int)MAX_STREAM, (int)MAX_STREAM); + pcon->trans_data_in = &parent_data_in; + pcon->header_size = 24; + rv = trans_attach(pcon, sck); + pcon->sck = sck; + printer->ccon = pcon; + + tc_mutex_unlock(mutex_pcon); + tc_mutex_unlock(mutex_print); + + if (rv > -1) { + + tc_mutex_lock(mutex_pcon); + tc_mutex_lock(mutex_print); + + /* add pcon to the set of monitored channels */ + if (pcon != NULL && pcon->sck > 0) { + objs[num_objs] = pcon->sck; + num_objs++; + check_parent = 1; + } + + /* add the appropriate ttyS* file descriptor to the set of monitored channels */ + if (printer->fd > 0) { + objs[num_objs] = printer->fd; + num_objs++; + check_device = 1; + } + + tc_mutex_unlock(mutex_pcon); + tc_mutex_unlock(mutex_print); + + /* monitor the above channels for input and respond appropriately */ + if (num_objs > 0 && objs[0] > -1) { + + tc_mutex_lock(mutex_pcon); + tc_mutex_lock(mutex_print); + + largs.printer = printer; + largs.pcon = pcon; + largs.objs[0] = objs[0]; + largs.objs[1] = objs[1]; + largs.num_objs = num_objs; + largs.timeout = timeout; + largs.check_parent = check_parent; + largs.check_device = check_device; + + tc_mutex_unlock(mutex_pcon); + tc_mutex_unlock(mutex_print); + + + if (objs != NULL && num_objs > 0 && (check_parent > 0 || check_device > 0)) { + tc_thread_init(&thread_parent,&loop_parent_print,&largs); + tc_thread_init(&thread_device,&loop_device_print,&largs); + tc_thread_join(thread_parent,NULL); + tc_thread_join(thread_device,NULL); + } + } + } + + return rv; +} + +static int APP_CC get_reqid(int * inarg) { + int rv = 0; + if (inarg == NULL) { + rv = -1; + } + else { + *inarg = -1; + tc_mutex_lock(mutex_reqid); + for (rv = 1; rv < MAX_REQID; rv++) { + if (g_reqids[rv].opid == -1) { + *inarg = rv; + g_reqids[rv].opid = rv; + tc_mutex_init(&(g_reqids[rv].mutex),NULL); + tc_cond_create(&(g_reqids[rv].cv),NULL); + break; + } + } + tc_mutex_unlock(mutex_reqid); + } + return rv; +} + +static int APP_CC free_reqid(int inarg) { + int rv = 0; + if (inarg < 0 || inarg > MAX_REQID) { + rv = -1; + } + else if (g_reqids[inarg].opid > -1 && g_reqids[inarg].opid <= MAX_REQID) { + tc_mutex_lock(mutex_reqid); + tc_mutex_deinit(&(g_reqids[inarg].mutex)); + tc_cond_deinit(&(g_reqids[inarg].cv)); + g_memset(&(g_reqids[inarg]),0,sizeof(callback)); + g_reqids[inarg].opid = -1; + tc_mutex_unlock(mutex_reqid); + } + return rv; +} + +static int APP_CC init_reqids() { + int rv = 0; + tc_mutex_lock(mutex_reqid); + g_memset((callback *)g_reqids,0,sizeof(callback)*MAX_REQID); + for (rv = 0; rv < MAX_REQID; rv++) { + g_reqids[rv].opid = -1; + } + tc_mutex_unlock(mutex_reqid); + rv = 0; + return rv; +} + +static int APP_CC get_mutex(int reqid, tc_t * inarg) { + int rv = 0; + + if (reqid >= 0 && reqid < MAX_REQID) { + tc_mutex_lock(mutex_reqid); + *inarg = (tc_t)g_reqids[reqid].mutex; + tc_mutex_unlock(mutex_reqid); + } + else { + rv = -1; + } + return rv; +} + +static int APP_CC get_cv(int reqid, tc_t * inarg) { + int rv = 0; + if (reqid >= 0 && reqid < MAX_REQID) { + tc_mutex_lock(mutex_reqid); + *inarg = (tc_t)(g_reqids[reqid].cv); + tc_mutex_unlock(mutex_reqid); + } + else { + rv = -1; + } + return rv; +} + +static char * APP_CC rdpprint_get_dircomponent(char * rv, const char * name) { + char * npos = (char *)NULL; + + if (name != NULL) { + npos = (char *)g_strrchr(name, (int)'/'); + if (npos > 0) { + if (rv == NULL) { + rv = (char *)g_malloc(sizeof(char) * ((npos - name) + 1), 1); + } + g_strncpy(rv, name, (npos - name)); + } + } + + return rv; +} + +/********************************************************/ +/* refactor a filename into canonical form */ +/********************************************************/ +static void APP_CC rdpprint_clean_fname(char * name) { + char * p = (char *)NULL; + char * p2 = (char *)NULL; + int l = 0; + int modified = 1; + const char forbidden[] = {'/', '[', ']', ':', '|', '<', '>', '+', '=', ';', ',', '?', 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f}; + + if (name == NULL) { + return; + } + + MDBGLOG("print","rdpprint_clean_fname() [%s]:\n", name); + + while (modified) { + modified = 0; + if ((p=strstr(name,"/./"))) { + modified = 1; + while (*p) { + p[0] = p[2]; + p++; + } + MDBGLOG("print", "\tclean 1 (/./) produced [%s]\n", name); + } + if ((p=strstr(name,"//"))) { + modified = 1; + while (*p) { + p[0] = p[1]; + p++; + } + MDBGLOG("print", "\tclean 2 (//) produced [%s]\n", name); + } + if (strcmp(name,"/../")==0) { + modified = 1; + name[1] = 0; + MDBGLOG("print", "\tclean 3 (^/../$) produced [%s]\n", name); + } + if ((p=strstr(name,"/../"))) { + modified = 1; + for (p2 = (p > name ? p-1 : p); p2 > name; p2--) { + if (p2[0] == '/') { + break; + } + } + if (p2 > name) p2++; + while (*p2) { + p2[0] = p[3]; + p2++; + p++; + } + MDBGLOG("print", "\tclean 4 (/../) produced [%s]\n", name); + } + + if (strcmp(name,"/..")==0) { + modified = 1; + name[1] = 0; + MDBGLOG("print", "\tclean 5 (^/..$) produced [%s]\n", name); + } + + l = strlen(name); + p = l>=3?(name+l-3):name; + if (strcmp(p,"/..")==0) { + modified = 1; + for (p2=p-1;p2>name;p2--) { + if (p2[0] == '/') break; + } + if (p2==name) { + p[0] = '/'; + p[1] = 0; + } else { + p2[0] = 0; + } + MDBGLOG("print", "\tclean 6 (/..) produced [%s]\n", name); + } + + l = strlen(name); + p = l>=2?(name+l-2):name; + if (strcmp(p,"/.")==0) { + modified = 1; + if (p == name) { + p[1] = 0; + } else { + p[0] = 0; + } + MDBGLOG("print", "\tclean 7 (/.) produced [%s]\n", name); + } + + if (strncmp(p=name,"./",2) == 0) { + modified = 1; + do { + p[0] = p[2]; + } while (*p++); + MDBGLOG("print", "\tclean 8 (^./) produced [%s]\n", name); + } + + l = strlen(p=name); + if (l > 1 && p[l-1] == '/') { + modified = 1; + p[l-1] = 0; + MDBGLOG("print", "\tclean 9 (/) produced [%s]\n", name); + } + } + + MDBGLOG("print","rdpprint_clean_fname() done [%s].\n", name); +} + +static int APP_CC ntstatus_to_errcode(DWORD ntstat) { + int retstat = 0; + + switch (ntstat) { + case 0: + retstat = 0; + break; + case STATUS_ACCESS_DENIED: + case STATUS_ACCESS_VIOLATION: + case STATUS_NETWORK_ACCESS_DENIED: + case STATUS_UNSUCCESSFUL: + retstat = -EACCES; + break; + case STATUS_GUARD_PAGE_VIOLATION: + case STATUS_INVALID_PARAMETER: + case STATUS_BAD_DEVICE_TYPE: + case STATUS_BAD_NETWORK_NAME: + case STATUS_INVALID_VOLUME_LABEL: + case STATUS_BAD_TOKEN_TYPE: + case STATUS_INVALID_GROUP_ATTRIBUTES: + case STATUS_BAD_MASTER_BOOT_RECORD: + case STATUS_INVALID_OPLOCK_PROTOCOL: + case STATUS_INVALID_INFO_CLASS: + case STATUS_INVALID_DEVICE_REQUEST: + case STATUS_INVALID_SYSTEM_SERVICE: + case STATUS_ILLEGAL_INSTRUCTION: + case STATUS_INVALID_LOCK_SEQUENCE: + case STATUS_INVALID_VIEW_SIZE: + case STATUS_INVALID_FILE_FOR_SECTION: + case STATUS_INVALID_DISPOSITION: + case STATUS_INVALID_UNWIND_TARGET: + case STATUS_INVALID_PORT_ATTRIBUTES: + case STATUS_INVALID_PARAMETER_MIX: + case STATUS_OBJECT_NAME_INVALID: + case STATUS_INVALID_VARIANT: + case STATUS_POWER_STATE_INVALID: + case STATUS_INVALID_DEVICE_OBJECT_PARAMETER: + case STATUS_INVALID_BLOCK_LENGTH: + retstat = -EINVAL; + break; +#ifdef ENOMEDIUM + case STATUS_NO_MEDIA_IN_DEVICE: + case STATUS_UNRECOGNIZED_MEDIA: + retstat = -ENOMEDIUM; + break; +#endif + case STATUS_SHARING_VIOLATION: + case STATUS_FILE_LOCK_CONFLICT: + case STATUS_LOCK_NOT_GRANTED: + case STATUS_SHARING_PAUSED: + case STATUS_SHARED_POLICY: + case STATUS_NOT_LOCKED: + case STATUS_PIPE_BUSY: + case STATUS_CONNECTION_IN_USE: + case STATUS_WAIT_FOR_OPLOCK: + retstat = -EBUSY; + break; + case STATUS_LOGON_FAILURE: + case STATUS_ACCOUNT_RESTRICTION: + case STATUS_ILL_FORMED_PASSWORD: + case STATUS_PASSWORD_RESTRICTION: + case STATUS_INVALID_LOGON_HOURS: + case STATUS_INVALID_WORKSTATION: + case STATUS_PASSWORD_EXPIRED: + case STATUS_ACCOUNT_DISABLED: + case STATUS_WRONG_PASSWORD: + case STATUS_SECTION_PROTECTION: + case STATUS_PRIVILEGE_NOT_HELD: + case STATUS_PRIVILEGED_INSTRUCTION: + case STATUS_PASSWORD_MUST_CHANGE: + case STATUS_ACCOUNT_LOCKED_OUT: + case STATUS_RESOURCE_NOT_OWNED: + case STATUS_LICENSE_VIOLATION: + case STATUS_LICENSE_QUOTA_EXCEEDED: + case STATUS_EVALUATION_EXPIRATION: + case STATUS_COPY_PROTECTION_FAILURE: + case STATUS_SMARTCARD_WRONG_PIN: + case STATUS_SMARTCARD_CARD_BLOCKED: + case STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED: + case STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT: + case STATUS_ACCESS_DISABLED_BY_POLICY_PATH: + case STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER: + case STATUS_ACCESS_DISABLED_BY_POLICY_OTHER: + case STATUS_CSS_AUTHENTICATION_FAILURE: + case STATUS_CSS_KEY_NOT_PRESENT: + case STATUS_CSS_KEY_NOT_ESTABLISHED: + case STATUS_INSUFFICIENT_LOGON_INFO: + retstat = -EPERM; + break; + case STATUS_DEVICE_DOES_NOT_EXIST: + case STATUS_DEVICE_NOT_CONNECTED: + case STATUS_DEVICE_POWER_FAILURE: + case STATUS_DEVICE_REMOVED: + case STATUS_PLUGPLAY_NO_DEVICE: + case STATUS_VOLUME_DISMOUNTED: + case STATUS_NOINTERFACE: + case STATUS_PARTITION_FAILURE: + retstat = -ENODEV; + break; + case STATUS_NO_MORE_FILES: + case STATUS_OBJECT_NAME_NOT_FOUND: + case STATUS_NOT_FOUND: + case STATUS_INVALID_PLUGPLAY_DEVICE_PATH: + case STATUS_NO_SUCH_FILE: + case STATUS_NETWORK_NAME_DELETED: + case STATUS_FILE_IS_OFFLINE: + case STATUS_MOUNT_POINT_NOT_RESOLVED: + retstat = -ENOENT; + break; + case STATUS_LOGON_SESSION_EXISTS: + case STATUS_DUPLICATE_NAME: + case STATUS_ALIAS_EXISTS: + case STATUS_ADDRESS_ALREADY_EXISTS: + case STATUS_DUPLICATE_OBJECTID: + case STATUS_OBJECTID_EXISTS: + retstat = -EEXIST; + break; + case STATUS_WRONG_VOLUME: + retstat = -EXDEV; + break; + case STATUS_BUFFER_TOO_SMALL: + case STATUS_SECTION_TOO_BIG: + case STATUS_SYSTEM_HIVE_TOO_LARGE: + retstat = -E2BIG; + break; + case STATUS_MEMORY_NOT_ALLOCATED: + case STATUS_NO_MEMORY: + case STATUS_INSUFFICIENT_RESOURCES: + case STATUS_INSUFF_SERVER_RESOURCES: + retstat = -ENOMEM; + break; + case STATUS_INVALID_HANDLE: + case STATUS_FILE_INVALID: + case STATUS_INVALID_PORT_HANDLE: + case STATUS_FILE_DELETED: + case STATUS_FILE_CLOSED: + case STATUS_FILE_CORRUPT_ERROR: + case STATUS_USER_MAPPED_FILE: + case STATUS_NOT_A_REPARSE_POINT: + case STATUS_DIRECTORY_IS_A_REPARSE_POINT: + case STATUS_FILE_NOT_ENCRYPTED: + case STATUS_FILE_ENCRYPTED: + case STATUS_CORRUPT_SYSTEM_FILE: + case STATUS_HANDLE_NOT_CLOSABLE: + retstat = -EBADF; + break; + case STATUS_FILES_OPEN: + retstat = -EMFILE; + break; + case STATUS_TOO_MANY_OPENED_FILES: + retstat = -ENFILE; + break; + case STATUS_PIPE_NOT_AVAILABLE: + case STATUS_INVALID_PIPE_STATE: + case STATUS_PIPE_BROKEN: + case STATUS_PIPE_EMPTY: + retstat = -EPIPE; + break; + case STATUS_DISK_FULL: + case STATUS_NO_LOG_SPACE: + case STATUS_LOG_FILE_FULL: + case STATUS_NO_SPOOL_SPACE: + case STATUS_PRINT_QUEUE_FULL: + case STATUS_DESTINATION_ELEMENT_FULL: + retstat = -ENOSPC; + break; + case STATUS_MEDIA_WRITE_PROTECTED: + retstat = -EROFS; + break; + case STATUS_DIRECTORY_NOT_EMPTY: + retstat = -ENOTEMPTY; + break; + case STATUS_RETRY: + retstat = -EAGAIN; + break; + case STATUS_OBJECT_PATH_NOT_FOUND: + case STATUS_NOT_A_DIRECTORY: + retstat = -ENOTDIR; + break; + case STATUS_FILE_IS_A_DIRECTORY: + retstat = -EISDIR; + break; + case STATUS_UNEXPECTED_IO_ERROR: + case STATUS_IO_PRIVILEGE_FAILED: + case STATUS_DEVICE_NOT_READY: + case STATUS_IO_DEVICE_ERROR: + case STATUS_OPEN_FAILED: + case STATUS_REPLY_MESSAGE_MISMATCH: + case STATUS_LOST_WRITEBEHIND_DATA: + retstat = -EIO; + break; + case STATUS_NOT_SUPPORTED: + case STATUS_ILLEGAL_FUNCTION: + case STATUS_WMI_NOT_SUPPORTED: + retstat = -EOPNOTSUPP; + break; + case STATUS_PIPE_DISCONNECTED: + case STATUS_CONNECTION_ABORTED: + case STATUS_CONNECTION_DISCONNECTED: + case STATUS_CONNECTION_RESET: + retstat = -ECONNRESET; + break; + default: + break; + } + + return retstat; +} + diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/rdpsc.c posixrdp/posixxrdp.orig/sesman/chansrv/rdpsc.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/rdpsc.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/rdpsc.c 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,1478 @@ +/* + * + * Smartcard redirection over RDP + * + */ + +#include "params.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" +#include "arch.h" +#include "parse.h" +#include "defines.h" +#include "rdpdr.h" +#include "rdpdr_methods.h" +#include "trans.h" +#include "devredir_defs.h" +#include "global.h" +#include "thread_calls.h" +#include "dbg.h" + +static int g_fd = -1; +static rdpsc * g_smartcard = (rdpsc *)NULL; + +static const uint32_t pmagic = RDP_PACKET_MAGIC; + +#ifndef MAX_REQID +#define MAX_REQID 25 +#endif +static callback g_reqids[MAX_REQID]; + +#ifndef MAX_MUTEX +#define MAX_MUTEX 25 +#endif +//static pthread_mutex_t g_mutexes[MAX_MUTEX]; +//static pthread_cond_t g_condition_variables[MAX_MUTEX]; + +//pthread_mutex_t mutex_device; +extern tc_t g_mutex; +extern tc_p mut; + +static tc_t g_mutex_pcon; +static tc_t g_mutex_smartcard; +static tc_t g_mutex_device; +static tc_t g_mutex_parent; +static tc_t g_mutex_smartcardop; +static tc_t g_mutex_reqid; +static tc_t g_mutex_device; +static tc_p mutex_pcon = (tc_p)NULL; +static tc_p mutex_smartcard = (tc_p)NULL; +static tc_p mutex_parent = (tc_p)NULL; +static tc_p mutex_smartcardop = (tc_p)NULL; +static tc_p mutex_reqid = (tc_p)NULL; +static tc_p mutex_device = (tc_p)NULL; + +static int APP_CC rdpsc_open(tbus); +static int APP_CC rdpsc_open_args(tbus, uint32_t, uint32_t, uint32_t, uint32_t); +static int APP_CC rdpsc_release(tbus); +static int APP_CC rdpsc_ioctl(tbus, int, size_t, void *, size_t, void *); + +static int APP_CC rdpsc_cycle(rdpsc *); + +static int APP_CC get_reqid(int *); +static int APP_CC free_reqid(int); +static int APP_CC init_reqids(void); +static int APP_CC get_mutex(int, tbus *); +static int APP_CC get_cv(int, tbus *); +static int APP_CC ntstatus_to_errcode(DWORD); + +extern int APP_CC get_RDPDR_HEADER(RDPDR_HEADER *, struct stream *); +extern int APP_CC get_DR_DEVICE_IOCOMPLETION(DR_DEVICE_IOCOMPLETION *, struct stream *); +extern int APP_CC get_DR_CREATE_RSP(DR_CREATE_RSP *, struct stream *); +extern int APP_CC get_DR_DRIVE_QUERY_INFORMATION_RSP(DR_DRIVE_QUERY_INFORMATION_RSP *, struct stream *); +extern int APP_CC get_DR_DRIVE_CREATE_RSP(DR_DRIVE_CREATE_RSP *, struct stream *); +extern int APP_CC construct_RDPDR_HEADER(RDPDR_HEADER *); +extern int APP_CC construct_DR_DEVICE_IOCOMPLETION(DR_DEVICE_IOCOMPLETION *); +extern int APP_CC construct_DR_CREATE_RSP(DR_CREATE_RSP *); +extern int APP_CC construct_DR_DRIVE_CREATE_RSP(DR_DRIVE_CREATE_RSP *); +extern char * APP_CC ntstatus_string(uint32_t); + +static int APP_CC parent_data_in(struct trans *); + +/* + * Port open operation + */ +int rdpsc_open(tbus fh) { + int retstat = 0; + struct stream * s = NULL; + int idx = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpsc_opcode = 0x00000000; + int size = 0x00000000; + rdpsc_data rdata; + tc_p lmutex = (tbus)NULL; + tc_p lcv = (tbus)NULL; + callback * cbdata = NULL; + uint32_t pflags = 0x00000000; + uint32_t pshare = 0x00000000; + uint32_t poptions = 0x00000000; + uint32_t pattributes = 0x00000000; + uint32_t magic = 0; + uint32_t crc32 = 0; + uint32_t calc_crc32 = 0; + int reqid = -1; + int uniqid = 0; + + MDBGLOG("smartcard","\n\nrdpsc_open (fh=\"%d\")\n",fh); + + g_memset(&rdata,0,sizeof(rdpsc_data)); + + tc_mutex_lock(mutex_smartcardop); + get_reqid(&reqid); + get_mutex(reqid, &lmutex); + tc_mutex_lock(lmutex); + tc_mutex_unlock(mutex_smartcardop); + + get_cv(reqid, &lcv); + cbdata = &(g_reqids[reqid]); + + pflags = GENERIC_ALL; + pshare |= (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE); + + rdpsc_opcode = RDPSC_OPEN; + uniqid = reqid; + + tc_mutex_lock(mutex_pcon); + pcon = g_smartcard->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, pmagic); + out_uint32_le(s, rdpsc_opcode); + out_uint32_le(s, size + 16); + out_uint32_le(s, fh); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + out_uint32_le(s, pflags); + out_uint32_le(s, pshare); + out_uint32_le(s, poptions); + out_uint32_le(s, pattributes); + s_mark_end(s); + size = s->end - s->data; + + g_hexdump_file("/tmp/taskq_smartcard_open.hexdump", s->data, size); + MDBGLOG("smartcard"," ** rdpsc_open(): sending [g_fd = %d]", g_fd); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + DBGLOG("smartcard","sent."); + tc_mutex_unlock(mutex_pcon); + + DBGLOG("smartcard","entering g_obj_wait loop:"); + tc_cond_wait(lcv, lmutex); + DBGLOG("smartcard","exiting g_obj_wait loop."); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("smartcard","ERROR [rdpsc_open()]: \"%s\" (retstat = %d; cbdata->IoStatus.Fields.Sev = 0x%8.8x)",nterr,retstat,cbdata->IoStatus.Value); + } + + MDBGLOG("smartcard","rdpsc_open(): done. (fh = %d; retstat = %d)",fh,retstat); + + tc_mutex_unlock(lmutex); + free_reqid(reqid); + + return retstat; +} + +int rdpsc_open_args(tbus fh, uint32_t pflags, uint32_t pshare, uint32_t poptions, uint32_t pattributes) { + int retstat = 0; + struct stream * s = NULL; + int idx = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpsc_opcode = 0x00000000; + int size = 0x00000000; + rdpsc_data rdata; + tc_p lmutex = (tbus)NULL; + tc_p lcv = (tbus)NULL; + callback * cbdata = NULL; + int reqid = -1; + int fhandle = 0; + int uniqid = 0; + uint32_t magic = 0; + uint32_t crc32 = 0; + uint32_t calc_crc32 = 0; + + MDBGLOG("smartcard","\n\nrdpsc_open_args (fh = \"%d\"; pflags = 0x%8.8x; pshare = 0x%8.8x; poptions = 0x%8.8x)\n",fh,pflags,pshare,poptions); + + g_memset(&rdata,0,sizeof(rdpsc_data)); + + tc_mutex_lock(mutex_smartcardop); + get_reqid(&reqid); + get_mutex(reqid, &lmutex); + tc_mutex_lock(lmutex); + tc_mutex_unlock(mutex_smartcardop); + + get_cv(reqid, &lcv); + cbdata = &(g_reqids[reqid]); + + rdpsc_opcode = RDPSC_OPEN; + uniqid = reqid; + + tc_mutex_lock(mutex_pcon); + pcon = g_smartcard->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, pmagic); + out_uint32_le(s, rdpsc_opcode); + out_uint32_le(s, size + 16); + out_uint32_le(s, fhandle); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + out_uint32_le(s, pflags); + out_uint32_le(s, pshare); + out_uint32_le(s, poptions); + out_uint32_le(s, pattributes); + s_mark_end(s); + size = s->end - s->data; + + g_hexdump_file("/tmp/taskq_smartcard_open_args.hexdump", s->data, size); + MDBGLOG("smartcard"," ** rdpsc_open_args(): sending [g_fd = %d]", g_fd); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + DBGLOG("smartcard","sent."); + tc_mutex_unlock(mutex_pcon); + + DBGLOG("smartcard","entering g_obj_wait loop:"); + tc_cond_wait(lcv, lmutex); + DBGLOG("smartcard","exiting g_obj_wait loop."); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("smartcard","ERROR [rdpsc_open_args()]: \"%s\" (retstat = %d; cbdata->IoStatus.Fields.Sev = 0x%8.8x)",nterr,retstat,cbdata->IoStatus.Value); + fhandle = -1; + } + + MDBGLOG("smartcard","rdpsc_open_args(): done. (fh = %d; retstat = %d)",fh,retstat); + + tc_mutex_unlock(lmutex); + free_reqid(reqid); + + return retstat; +} + +/** Read data from an open file + * + * Read should return exactly the number of bytes requested except + * on EOF or error, otherwise the rest of the data will be + * substituted with zeroes. An exception to this is when the + * 'direct_io' mount option is specified, in which case the return + * value of the read system call will reflect the return value of + * this operation. + * + * Changed in version 2.2 + */ +// I don't fully understand the documentation above -- it doesn't +// match the documentation for the read() system call which says it +// can return with anything up to the amount of data requested. nor +// with the fusexmp code which returns the amount of data also +// returned by read. + +int rdpsc_read_chunk(tbus fh, char * buf, size_t size) { + int retstat = 0; + int plen = 0; + struct stream * s = NULL; + int idx = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpsc_opcode = 0x00000000; + int reqid = -1; + int uniqid = 0; + tc_p lmutex = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + callback * cbdata = NULL; + int mode = 0; + size_t fsize = 0; + uint32_t magic = 0; + uint32_t crc32 = 0; + uint32_t calc_crc32 = 0; + + tc_mutex_lock(mutex_smartcardop); + get_reqid(&reqid); + get_mutex(reqid, &lmutex); + tc_mutex_lock(lmutex); + tc_mutex_unlock(mutex_smartcardop); + + cbdata = &(g_reqids[reqid]); + cbdata->userdata = buf; + + rdpsc_opcode = RDPSC_READ; + uniqid = reqid; + + tc_mutex_lock(mutex_pcon); + pcon = g_smartcard->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, pmagic); + out_uint32_le(s, rdpsc_opcode); + out_uint32_le(s, 4); + out_uint32_le(s, fh); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + out_uint32_le(s, size); + s_mark_end(s); + fsize = s->end - s->data; + g_hexdump_file("/tmp/taskq_smartcard_read_chunk_cmd.hexdump", s->data, fsize); + trans_force_write(pcon); + g_memset(s->data,0,sizeof(char)*MAX_STREAM); + tc_mutex_unlock(mutex_pcon); + DBGLOG("smartcard","sent."); + + DBGLOG("smartcard"," Entering wait loop..."); + get_cv(reqid,&lcv); + tc_cond_wait(lcv,lmutex); + DBGLOG("smartcard"," Finished."); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + const char * nterr = (const char *)ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("smartcard","ERROR [rdpsc_read_chunk()]: \"%s\" (retstat = %d; cbdata->IoStatus.Value = 0x%8.8x)",nterr,retstat,cbdata->IoStatus.Value); + //retstat = 0; + } + else { + retstat = cbdata->length; + } + g_hexdump_file("/tmp/taskq_smartcard_read_chunk_result.hexdump", cbdata->userdata, cbdata->length); + g_memset(cbdata,0,sizeof(callback)); + + tc_mutex_unlock(lmutex); + free_reqid(reqid); + + return retstat; +} + +int rdpsc_read(tbus fh, char * buf, size_t size) { + #ifndef CHUNK_SIZE + #define CHUNK_SIZE 4096 + #endif + int retstat = 0; + struct stream * s = NULL; + int idx = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpsc_opcode = 0x00000000; + int reqid = -1; + int uniqid = 0; + tc_p lmutex = (tbus)NULL; + tc_p lcv = (tbus)NULL; + callback * cbdata = NULL; + int mode = 0; + int chunks = 0; + char * tpos = NULL; + off_t toffset = 0; + size_t tsize = 0; + uint64_t tally = 0; + + MDBGLOG("smartcard","rdpsc_read(): fh = %d; size = %d",fh,size); + + chunks = (size == 0) ? 0 : 1; + if (size > CHUNK_SIZE) { + chunks = ((size % CHUNK_SIZE) == 0) ? size / CHUNK_SIZE : (size / CHUNK_SIZE) + 1; + } + + for (idx = 0; idx < chunks; idx++) { + tpos = buf + (idx * CHUNK_SIZE); + toffset = 0; + tsize = (idx == (chunks - 1) && (size % CHUNK_SIZE) != 0) ? size % CHUNK_SIZE : CHUNK_SIZE; + retstat = rdpsc_read_chunk(fh,tpos,tsize); + if (retstat < 0) { + break; + } + else { + tally += retstat; + } + } + if (retstat > -1) { + retstat = tally; + } + + return retstat; +} + +/** Write data to an open file + * + * Write should return exactly the number of bytes requested + * except on error. An exception to this is when the 'direct_io' + * mount option is specified (see read operation). + * + * Changed in version 2.2 + */ +int rdpsc_write_chunk(tbus fh, const char * buf, size_t size) { + int retstat = 0; + struct stream * s = NULL; + int idx = 0; + int fsize = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpsc_opcode = 0x00000000; + int reqid = -1; + int uniqid = 0; + tc_p lmutex = (tbus)NULL; + tc_p lcv = (tbus)NULL; + callback * cbdata = NULL; + uint32_t magic = 0; + uint32_t crc32 = 0; + uint32_t calc_crc32 = 0; + + tc_mutex_lock(mutex_smartcardop); + get_reqid(&reqid); + get_mutex(reqid, &lmutex); + tc_mutex_lock(lmutex); + tc_mutex_unlock(mutex_smartcardop); + + cbdata = &(g_reqids[reqid]); + cbdata->userdata = (char *)buf; + + rdpsc_opcode = RDPSC_WRITE; + uniqid = reqid; + + tc_mutex_lock(mutex_pcon); + pcon = g_smartcard->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, pmagic); + out_uint32_le(s, rdpsc_opcode); + out_uint32_le(s, size); + out_uint32_le(s, fh); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + if (size > 0) { + out_uint8a(s, buf, size); + } + s_mark_end(s); + fsize = s->end - s->data; + g_hexdump_file("/tmp/taskq_smartcard_write_chunk_cmd.hexdump", s->data, fsize); + trans_force_write(pcon); + g_memset(s->data,0,sizeof(char)*MAX_STREAM); + tc_mutex_unlock(mutex_pcon); + DBGLOG("smartcard","sent."); + + DBGLOG("smartcard"," Entering wait loop..."); + get_cv(reqid,&lcv); + tc_cond_wait(lcv,lmutex); + DBGLOG("smartcard"," Finished."); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + MDBGLOG("smartcard","ERROR [rdpsc_write_chunk()]: retstat = %d; cbdata->IoStatus.Value = %d",retstat,cbdata->IoStatus.Value); + } + else { + retstat = cbdata->length; + } + g_hexdump_file("/tmp/taskq_smartcard_write_chunk_result.hexdump", cbdata->userdata, cbdata->length); + g_memset(cbdata,0,sizeof(callback)); + + tc_mutex_unlock(lmutex); + free_reqid(reqid); + + return retstat; +} + +int rdpsc_write(tbus fh, const char * buf, size_t size) { + #ifndef CHUNK_SIZE + #define CHUNK_SIZE 4096 + #endif + int retstat = 0; + struct stream * s = NULL; + int idx = 0; + int fsize = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpsc_opcode = 0x00000000; + int reqid = -1; + int uniqid = 0; + tc_p lmutex = (tbus)NULL; + tc_p lcv = (tbus)NULL; + callback * cbdata = NULL; + int mode = 0; + int chunks = 0; + char * tpos = (BYTE *)NULL; + off_t toffset = 0; + size_t tsize = 0; + uint64_t tally = 0; + + chunks = (size == 0) ? 0 : 1; + if (size > CHUNK_SIZE) { + chunks = ((size % CHUNK_SIZE) == 0) ? size / CHUNK_SIZE : (size / CHUNK_SIZE) + 1; + } + + for (idx = 0; idx < chunks; idx++) { + tpos = (char *)buf + (idx * CHUNK_SIZE); + tsize = (idx == (chunks - 1) && (size % CHUNK_SIZE) != 0) ? size % CHUNK_SIZE : CHUNK_SIZE; + retstat = rdpsc_write_chunk(fh,tpos,tsize); + if (retstat < 0) { + break; + } + else { + tally += retstat; + } + } + if (retstat > -1) { + retstat = tally; + } + + return retstat; +} + +/** Release an open file + * + */ +int rdpsc_release(tbus fh) { + int retstat = 0; + struct stream * s = NULL; + int idx = 0; + struct trans * pcon = (struct trans *)NULL; + int rdpsc_opcode = 0x00000000; + int size = 0x00000000; + rdpsc_data rdata; + int uniqid = 0; + int reqid = -1; + callback * cbdata = NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + uint32_t magic = 0; + uint32_t crc32 = 0; + uint32_t calc_crc32 = 0; + + tc_mutex_lock(mutex_smartcardop); + get_reqid(&reqid); + get_mutex(reqid,&lmut); + tc_mutex_lock(lmut); + tc_mutex_unlock(mutex_smartcardop); + + MDBGLOG("smartcard","\n\nrdpsc_release(fh=\"%d\")\n",fh); + g_memset(&rdata,0,sizeof(rdpsc_data)); + + rdpsc_opcode = RDPSC_CLOSE; + uniqid = reqid; + cbdata = &(g_reqids[reqid]); + cbdata->FileId = fh; + + tc_mutex_lock(mutex_pcon); + pcon = g_smartcard->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, pmagic); + out_uint32_le(s, rdpsc_opcode); + out_uint32_le(s, size); + out_uint32_le(s, fh); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + s_mark_end(s); + size = s->end - s->data; + MDBGLOG("smartcard"," ** rdpsc_release(): sending [g_fd = %d]", g_fd); + trans_force_write(pcon); + DBGLOG("smartcard","sent."); + g_hexdump_file("/tmp/taskq_smartcard_release.hexdump", s->data, size); + g_memset(s->data,0,MAX_STREAM); + tc_mutex_unlock(mutex_pcon); + + get_cv(reqid,&lcv); + DBGLOG("smartcard"," Waiting..."); + tc_cond_wait(lcv,lmut); + DBGLOG("smartcard"," Done."); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + //retstat = rdpsc_error("rdpsc_release lstat"); + MDBGLOG("smartcard","ERROR [rdpsc_release()]: \"%s\" (retstat = %d)",nterr,retstat); + } + + MDBGLOG("smartcard","rdpsc_release(): done. ()"); + + tc_mutex_unlock(lmut); + free_reqid(reqid); + + return retstat; +} + +/* + * + * Ioctl + * + */ +int rdpsc_ioctl(tbus fh, int cmd, size_t argslen, void * args, size_t buflen, void * buf) { + int retstat = 0; + struct stream * s = NULL; + struct trans * pcon = (struct trans *)NULL; + int rdpsc_opcode = 0x00000000; + int size = 0x00000000; + rdpsc_data rdata; + tc_p lmutex = (tbus)NULL; + tc_p lcv = (tbus)NULL; + callback * cbdata = NULL; + int reqid = -1; + int uniqid = 0; + uint32_t magic = 0; + uint32_t crc32 = 0; + uint32_t calc_crc32 = 0; + + tc_mutex_lock(mutex_smartcardop); + get_reqid(&reqid); + get_mutex(reqid, &lmutex); + tc_mutex_lock(lmutex); + tc_mutex_unlock(mutex_smartcardop); + + MDBGLOG("smartcard","\n\nrdpsc_ioctl (fh=\"%d\"; argslen=\"%d\"; buflen=\"%d\")\n",fh,argslen,buflen); + + g_memset(&rdata,0,sizeof(rdpsc_data)); + + get_cv(reqid, &lcv); + cbdata = &(g_reqids[reqid]); + + rdpsc_opcode = RDPSC_IOCTL; + uniqid = reqid; + size = argslen; + + tc_mutex_lock(mutex_pcon); + pcon = g_smartcard->ccon; + pcon->callback_data = cbdata; + s = trans_get_out_s(pcon, MAX_STREAM); + out_uint32_le(s, pmagic); + out_uint32_le(s, rdpsc_opcode); + out_uint32_le(s, size + 4); + out_uint32_le(s, fh); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + out_uint32_le(s, cmd); + if (argslen > 0) { + out_uint8a(s, (char *)args, argslen); + } + s_mark_end(s); + size = s->end - s->data; + + g_hexdump_file("/tmp/taskq_smartcard_ioctl.hexdump", s->data, size); + MDBGLOG("smartcard"," ** rdpsc_ioctl(): sending [g_fd = %d; fh = %d; size = %d]", g_fd, argslen, size); + trans_force_write(pcon); + g_memset(s->data,0,MAX_STREAM); + DBGLOG("smartcard","sent."); + tc_mutex_unlock(mutex_pcon); + + DBGLOG("smartcard","entering g_obj_wait loop:"); + tc_cond_wait(lcv, lmutex); + DBGLOG("smartcard","exiting g_obj_wait loop."); + + retstat = ntstatus_to_errcode(cbdata->IoStatus.Value); + if (retstat < 0) { + char * nterr = ntstatus_string(cbdata->IoStatus.Value); + MDBGLOG("smartcard","ERROR [rdpsc_ioctl()]: \"%s\" (cbdata->IoStatus.Fields.Sev == STATUS_SEVERITY_ERROR)",nterr); + } + + DBGLOG("smartcard","rdpsc_ioctl(): done."); + + tc_mutex_unlock(lmutex); + free_reqid(reqid); + + return retstat; +} + + +/*****************************************************************************/ +/***** child process-related section ******/ +/*****************************************************************************/ + + +/*****************************************************************************/ +static int APP_CC +parent_data_in(struct trans * trans) { + struct stream * s = (struct stream *)NULL; + int rdpsc_opcode = 0; + int rdpsc_reply = 0; + int size = 0; + int error = 0; + int fault = 0; + int fhandle = 0; + int uniqid = 0; + int fdone = 0; + uint32_t magic = 0; + uint32_t crc32 = 0; + uint32_t calc_crc32 = 0; + BYTE buf[MAX_STREAM]; + + DBGLOG("smartcard","parent_data_in(): called"); + + g_memset((BYTE *)buf,0,sizeof(BYTE)*MAX_STREAM); + + if (trans == 0) + { + return 0; + } + tc_mutex_lock(mutex_pcon); + s = (struct stream *)trans_get_in_s(trans); + in_uint32_le(s, magic); + in_uint32_le(s, rdpsc_reply); + in_uint32_le(s, size); + in_uint32_le(s, fhandle); + in_uint32_le(s, uniqid); + in_uint32_le(s, crc32); + if (size > 0) { + error = trans_force_read(trans, size); + } + if (error == 0) + { + /* the entire message block has been read in, so process it: */ + fault = ((rdpsc_reply & RDPSC_ERROR) == 0) ? 0 : 1; + rdpsc_opcode = rdpsc_reply & (~(RDPSC_REPLY | RDPSC_ERROR)); + MDBGLOG("smartcard"," ** parent_data_in(): rdpsc_opcode = 0x%8.8x; rdpsc_reply = 0x%8.8x; fault = %d; uniqid = %d",rdpsc_opcode,rdpsc_reply,fault,uniqid); + if (fault > 0) { + NTSTATUS iostatus = { .Value = 0x00000000 }; + int reqid = -1; + callback * cbdata = NULL; + tc_p lmut = (tc_p)NULL; + tc_p lcv = (tc_p)NULL; + char * nterr = (char *)NULL; + + tc_mutex_lock(mutex_smartcardop); + in_uint32_le(s, iostatus.Value); + + nterr = ntstatus_string(iostatus.Value); + MDBGLOG("smartcard"," --> FAULT: \"%s\" (status = 0x%8.8x)",nterr,iostatus.Value); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + if (reqid > -1) { + get_mutex(reqid, &lmut); + tc_mutex_lock(lmut); + tc_mutex_unlock(mutex_smartcardop); + cbdata->IoStatus.Value = iostatus.Value; + get_cv(reqid, &lcv); + tc_cond_signal(lcv); + } + else { + lmut = mutex_smartcardop; + } + tc_mutex_unlock(lmut); + } + else switch(rdpsc_opcode) { + case RDPSC_OPEN: + DBGLOG("smartcard"," ^^ (RDPSC_OPEN)"); + { + DR_DRIVE_CREATE_RSP iorsp; + int reqid = -1; + callback * cbdata = NULL; + tc_p lmut = (tbus)NULL; + tc_p lcv = (tbus)NULL; + tc_mutex_lock(mutex_smartcardop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex(reqid, &lmut); + tc_mutex_lock(lmut); + tc_mutex_unlock(mutex_smartcardop); + get_cv(reqid, &lcv); + construct_DR_DRIVE_CREATE_RSP(&iorsp); + if (size > 0 && size < MAX_STREAM) { + get_DR_DRIVE_CREATE_RSP(&iorsp, s); + } + cbdata->FileId = iorsp.DeviceCreateResponse.FileId; + MDBGLOG("smartcard"," --> FileId = %d; fhandle = %d",cbdata->FileId,fhandle); + { + int tsize = 0; + char vdata[MAX_STREAM]; + struct stream vs; + struct stream * v = &vs; + g_memset(&vdata,0,sizeof(char)*MAX_STREAM); + g_memset(v,0,sizeof(struct stream)); + v->data = (char *)(&vdata); + v->p = v->data; + v->end = v->data; + v->size = MAX_STREAM; + send_DR_DRIVE_CREATE_RSP(&iorsp, v); + s_mark_end(v); + tsize = v->end - v->data; + g_hexdump_file("/tmp/taskq_smartcard_open_reply.hexdump",v->data,tsize); + } + tc_cond_signal(lcv); + tc_mutex_unlock(lmut); + } + break; + case RDPSC_READ: + DBGLOG("smartcard"," ^^ (RDPSC_READ)"); + { + DR_DRIVE_READ_RSP iorsp; + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tbus)NULL; + tc_p lcv = (tbus)NULL; + tc_mutex_lock(mutex_smartcardop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex(reqid, &lmut); + tc_mutex_lock(lmut); + tc_mutex_unlock(mutex_smartcardop); + construct_DR_READ_RSP(&iorsp); + iorsp.ReadData = cbdata->userdata; + get_DR_READ_RSP(&iorsp, s); + cbdata->length = iorsp.Length; + get_cv(reqid,&lcv); + tc_cond_signal(lcv); + tc_mutex_unlock(lmut); + MDBGLOG("smartcard"," ^^ (RDPSC_READ): iorsp.Length = %d; iorsp.ReadData = \"%s\"",iorsp.Length,iorsp.ReadData); + } + break; + case RDPSC_WRITE: + DBGLOG("smartcard"," ^^ (RDPSC_WRITE)"); + { + DR_DRIVE_WRITE_RSP iorsp; + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tbus)NULL; + tc_p lcv = (tbus)NULL; + tc_mutex_lock(mutex_smartcardop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex(reqid, &lmut); + tc_mutex_lock(lmut); + tc_mutex_unlock(mutex_smartcardop); + construct_DR_WRITE_RSP(&iorsp); + get_DR_WRITE_RSP(&iorsp, s); + cbdata->length = iorsp.Length; + get_cv(reqid,&lcv); + tc_cond_signal(lcv); + tc_mutex_unlock(lmut); + } + break; + case RDPSC_IOCTL: + DBGLOG("smartcard"," ^^ (RDPSC_IOCTL)"); + { + DR_CONTROL_RSP iorsp; + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tbus)NULL; + tc_p lcv = (tbus)NULL; + tc_mutex_lock(mutex_smartcardop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex(reqid, &lmut); + tc_mutex_lock(lmut); + tc_mutex_unlock(mutex_smartcardop); + construct_DR_CONTROL_RSP(&iorsp); + iorsp.OutputBuffer = cbdata->userdata; + get_DR_CONTROL_RSP(&iorsp, s); + cbdata->length = iorsp.OutputBufferLength; + get_cv(reqid,&lcv); + tc_cond_signal(lcv); + tc_mutex_unlock(lmut); + MDBGLOG("smartcard"," ^^ (RDPSC_IOCTL): iorsp.OutputBufferLength = %d;",iorsp.OutputBufferLength); + } + break; + case RDPSC_CLOSE: + DBGLOG("smartcard"," ^^ (RDPSC_CLOSE)"); + { + int reqid = -1; + callback * cbdata = (callback *)NULL; + tc_p lmut = (tbus)NULL; + tc_p lcv = (tbus)NULL; + tc_mutex_lock(mutex_smartcardop); + cbdata = &(g_reqids[uniqid]); + reqid = cbdata->opid; + get_mutex(reqid, &lmut); + tc_mutex_lock(lmut); + tc_mutex_unlock(mutex_smartcardop); + get_cv(reqid,&lcv); + tc_cond_signal(lcv); + tc_mutex_unlock(lmut); + } + break; + case RDPSC_INIT: + DBGLOG("smartcard"," ^^ (RDPSC_INIT)"); + { + int reqid = -1; + callback * cbdata = (callback *)NULL; + filelist * lst = (filelist *)NULL; + tc_p lmut = (tbus)NULL; + tc_p lcv = (tbus)NULL; + } + break; + case RDPSC_DESTROY: + DBGLOG("smartcard"," ^^ (RDPSC_DESTROY)"); + exit(0); + break; + case RDPSC_ERROR: + DBGLOG("smartcard"," ^^ (RDPSC_ERROR)"); + exit(0); + break; + } + } + tc_mutex_unlock(mutex_pcon); + return error; +} + +typedef struct _handle_smartcard_loop_args { + rdpsc * smartcard; + struct trans * pcon; + tbus objs[2]; + int num_objs; + int timeout; + int check_parent; + int check_device; +} handle_smartcard_loop_args; + +static void * APP_CC +loop_parent_sc(void * inargs) { + handle_smartcard_loop_args * largs = (handle_smartcard_loop_args *)inargs; + rdpsc * smartcard = largs->smartcard; + struct trans * pcon = largs->pcon; + tbus * objs = (tbus *)(largs->objs); + int num_objs = largs->num_objs; + int timeout = largs->timeout; + int check_parent = largs->check_parent; + int check_device = largs->check_device; + if (inargs != NULL && objs != NULL && num_objs > 0 && check_parent > 0) { + /* handle any inbound communication from the parent process: */ + while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) { + if ((check_parent > 0) && g_is_wait_obj_set(objs[0])) { + tc_mutex_lock(mutex_parent); + if (trans_check_wait_objs(pcon) != 0) { + DBGLOG("smartcard","ERROR [loop_parent_sc()]: "); + //rv = -1; + break; + } + tc_mutex_unlock(mutex_parent); + } + } + } + tc_thread_exit(NULL); +} + +static void * APP_CC +loop_device_sc(void * inargs) { + handle_smartcard_loop_args * largs = (handle_smartcard_loop_args *)inargs; + rdpsc * smartcard = largs->smartcard; + struct trans * pcon = largs->pcon; + tbus * objs = (tbus *)(largs->objs); + int num_objs = largs->num_objs; + int timeout = largs->timeout; + int check_parent = largs->check_parent; + int check_device = largs->check_device; + if (inargs != NULL && objs != NULL && num_objs > 0 && check_device > 0) { + /* handle communication from pseudo-device (i.e., the artificial serial or parallel smartcard on the server): */ + while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) { + if ((check_device > 0) && ((num_objs == 2 && g_is_wait_obj_set(objs[1])) || (num_objs == 1 && g_is_wait_obj_set(objs[0])))) { + tc_mutex_lock(mutex_device); + rdpsc_cycle(smartcard); + tc_mutex_unlock(mutex_device); + } + } + } + tc_thread_exit(NULL); +} + +/*****************************************************************************/ +static int APP_CC +rdpsc_cycle(rdpsc * smartcard) { + int rv = 0; + return rv; +} + +/*****************************************************************************/ +int APP_CC +handle_smartcard(tbus sck, rdpsc * smartcard) { + int rv = 0; + int brk = 0; + struct trans * pcon = (struct trans *)NULL; + tbus objs[2] = { -1, -1 }; + int num_objs = 0; + int timeout = 0; + int check_parent = 0; + int check_device = 0; + handle_smartcard_loop_args largs; + tc_thread_t thread_parent; + tc_thread_t thread_device; + + MDBGLOG("smartcard","handle_smartcard(): sck = %d",sck); + g_memset(&largs,0,sizeof(handle_smartcard_loop_args)); + g_memset(&thread_parent,0,sizeof(tbus)); + g_memset(&thread_device,0,sizeof(tbus)); + + mut = (tc_p)&g_mutex; + mutex_pcon = (tc_p)&g_mutex_pcon; + mutex_smartcard = (tc_p)&g_mutex_smartcard; + mutex_smartcardop = (tc_p)&g_mutex_smartcardop; + mutex_parent = (tc_p)&g_mutex_parent; + mutex_device = (tc_p)&g_mutex_device; + mutex_reqid = (tc_p)&g_mutex_reqid; + tc_mutex_init(mut,NULL); + tc_mutex_init(mutex_pcon,NULL); + tc_mutex_init(mutex_smartcard,NULL); + tc_mutex_init(mutex_smartcardop,NULL); + tc_mutex_init(mutex_parent,NULL); + tc_mutex_init(mutex_device,NULL); + tc_mutex_init(mutex_reqid,NULL); + + tc_mutex_lock(mutex_pcon); + tc_mutex_lock(mutex_smartcard); + + init_reqids(); + + /* set up pcon as a transmission channel to the parent */ + pcon = (struct trans *)trans_create((int)2, (int)MAX_STREAM, (int)MAX_STREAM); + pcon->trans_data_in = &parent_data_in; + pcon->header_size = 24; + rv = trans_attach(pcon, sck); + pcon->sck = sck; + smartcard->ccon = pcon; + + tc_mutex_unlock(mutex_pcon); + tc_mutex_unlock(mutex_smartcard); + + if (rv > -1) { + + tc_mutex_lock(mutex_pcon); + tc_mutex_lock(mutex_smartcard); + + /* add pcon to the set of monitored channels */ + if (pcon != NULL && pcon->sck > 0) { + objs[num_objs] = pcon->sck; + num_objs++; + check_parent = 1; + } + + /* add the appropriate ttyS* file descriptor to the set of monitored channels */ + if (smartcard->fd > 0) { + objs[num_objs] = smartcard->fd; + num_objs++; + check_device = 1; + } + + tc_mutex_unlock(mutex_pcon); + tc_mutex_unlock(mutex_smartcard); + + /* monitor the above channels for input and respond appropriately */ + if (num_objs > 0 && objs[0] > -1) { + + tc_mutex_lock(mutex_pcon); + tc_mutex_lock(mutex_smartcard); + + largs.smartcard = smartcard; + largs.pcon = pcon; + largs.objs[0] = objs[0]; + largs.objs[1] = objs[1]; + largs.num_objs = num_objs; + largs.timeout = timeout; + largs.check_parent = check_parent; + largs.check_device = check_device; + + tc_mutex_unlock(mutex_pcon); + tc_mutex_unlock(mutex_smartcard); + + + if (objs != NULL && num_objs > 0 && (check_parent > 0 || check_device > 0)) { + tc_thread_init(&thread_parent,&loop_parent_sc,&largs); + tc_thread_init(&thread_device,&loop_device_sc,&largs); + tc_thread_join(thread_parent,NULL); + tc_thread_join(thread_device,NULL); + } + } + } + + return rv; +} + +static int APP_CC get_reqid(int * inarg) { + int rv = 0; + if (inarg == NULL) { + rv = -1; + } + else { + *inarg = -1; + tc_mutex_lock(mutex_reqid); + for (rv = 1; rv < MAX_REQID; rv++) { + if (g_reqids[rv].opid == -1) { + *inarg = rv; + g_reqids[rv].opid = rv; + tc_mutex_init(&(g_reqids[rv].mutex),NULL); + tc_cond_create(&(g_reqids[rv].cv),NULL); + break; + } + } + tc_mutex_unlock(mutex_reqid); + } + return rv; +} + +static int APP_CC free_reqid(int inarg) { + int rv = 0; + if (inarg < 0 || inarg > MAX_REQID) { + rv = -1; + } + else if (g_reqids[inarg].opid > -1 && g_reqids[inarg].opid <= MAX_REQID) { + tc_mutex_lock(mutex_reqid); + tc_mutex_deinit(&(g_reqids[inarg].mutex)); + tc_cond_deinit(&(g_reqids[inarg].cv)); + g_memset(&(g_reqids[inarg]),0,sizeof(callback)); + g_reqids[inarg].opid = -1; + tc_mutex_unlock(mutex_reqid); + } + return rv; +} + +static int APP_CC init_reqids() { + int rv = 0; + tc_mutex_lock(mutex_reqid); + g_memset((callback *)g_reqids,0,sizeof(callback)*MAX_REQID); + for (rv = 0; rv < MAX_REQID; rv++) { + g_reqids[rv].opid = -1; + } + tc_mutex_unlock(mutex_reqid); + rv = 0; + return rv; +} + +static int APP_CC get_mutex(int reqid, tbus * inarg) { + int rv = 0; + + if (reqid >= 0 && reqid < MAX_REQID) { + tc_mutex_lock(mutex_reqid); + *inarg = (tbus)&(g_reqids[reqid].mutex); + tc_mutex_unlock(mutex_reqid); + } + else { + rv = -1; + } + return rv; +} + +static int APP_CC get_cv(int reqid, tbus* inarg) { + int rv = 0; + if (reqid >= 0 && reqid < MAX_REQID) { + tc_mutex_lock(mutex_reqid); + *inarg = (tbus)&(g_reqids[reqid].cv); + tc_mutex_unlock(mutex_reqid); + } + else { + rv = -1; + } + return rv; +} + +static char * APP_CC rdpsc_get_dircomponent(char * rv, const char * name) { + char * npos = (char *)NULL; + + if (name != NULL) { + npos = (char *)g_strrchr(name, (int)'/'); + if (npos > 0) { + if (rv == NULL) { + rv = (char *)g_malloc(sizeof(char) * ((npos - name) + 1), 1); + } + g_strncpy(rv, name, (npos - name)); + } + } + + return rv; +} + +/********************************************************/ +/* refactor a filename into canonical form */ +/********************************************************/ +static void APP_CC rdpsc_clean_fname(char * name) { + char * p = (char *)NULL; + char * p2 = (char *)NULL; + int l = 0; + int modified = 1; + const char forbidden[] = {'/', '[', ']', ':', '|', '<', '>', '+', '=', ';', ',', '?', 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f}; + + if (name == NULL) { + return; + } + + MDBGLOG("smartcard","rdpsc_clean_fname() [%s]:\n", name); + + while (modified) { + modified = 0; + if ((p=strstr(name,"/./"))) { + modified = 1; + while (*p) { + p[0] = p[2]; + p++; + } + MDBGLOG("smartcard", "\tclean 1 (/./) produced [%s]\n", name); + } + if ((p=strstr(name,"//"))) { + modified = 1; + while (*p) { + p[0] = p[1]; + p++; + } + MDBGLOG("smartcard", "\tclean 2 (//) produced [%s]\n", name); + } + if (strcmp(name,"/../")==0) { + modified = 1; + name[1] = 0; + MDBGLOG("smartcard", "\tclean 3 (^/../$) produced [%s]\n", name); + } + if ((p=strstr(name,"/../"))) { + modified = 1; + for (p2 = (p > name ? p-1 : p); p2 > name; p2--) { + if (p2[0] == '/') { + break; + } + } + if (p2 > name) p2++; + while (*p2) { + p2[0] = p[3]; + p2++; + p++; + } + MDBGLOG("smartcard", "\tclean 4 (/../) produced [%s]\n", name); + } + + if (strcmp(name,"/..")==0) { + modified = 1; + name[1] = 0; + MDBGLOG("smartcard", "\tclean 5 (^/..$) produced [%s]\n", name); + } + + l = strlen(name); + p = l>=3?(name+l-3):name; + if (strcmp(p,"/..")==0) { + modified = 1; + for (p2=p-1;p2>name;p2--) { + if (p2[0] == '/') break; + } + if (p2==name) { + p[0] = '/'; + p[1] = 0; + } else { + p2[0] = 0; + } + MDBGLOG("smartcard", "\tclean 6 (/..) produced [%s]\n", name); + } + + l = strlen(name); + p = l>=2?(name+l-2):name; + if (strcmp(p,"/.")==0) { + modified = 1; + if (p == name) { + p[1] = 0; + } else { + p[0] = 0; + } + MDBGLOG("smartcard", "\tclean 7 (/.) produced [%s]\n", name); + } + + if (strncmp(p=name,"./",2) == 0) { + modified = 1; + do { + p[0] = p[2]; + } while (*p++); + MDBGLOG("smartcard", "\tclean 8 (^./) produced [%s]\n", name); + } + + l = strlen(p=name); + if (l > 1 && p[l-1] == '/') { + modified = 1; + p[l-1] = 0; + MDBGLOG("smartcard", "\tclean 9 (/) produced [%s]\n", name); + } + } + + MDBGLOG("smartcard","rdpsc_clean_fname() done [%s].\n", name); +} + +static int APP_CC ntstatus_to_errcode(DWORD ntstat) { + int retstat = 0; + + switch (ntstat) { + case 0: + retstat = 0; + break; + case STATUS_ACCESS_DENIED: + case STATUS_ACCESS_VIOLATION: + case STATUS_NETWORK_ACCESS_DENIED: + case STATUS_UNSUCCESSFUL: + retstat = -EACCES; + break; + case STATUS_GUARD_PAGE_VIOLATION: + case STATUS_INVALID_PARAMETER: + case STATUS_BAD_DEVICE_TYPE: + case STATUS_BAD_NETWORK_NAME: + case STATUS_INVALID_VOLUME_LABEL: + case STATUS_BAD_TOKEN_TYPE: + case STATUS_INVALID_GROUP_ATTRIBUTES: + case STATUS_BAD_MASTER_BOOT_RECORD: + case STATUS_INVALID_OPLOCK_PROTOCOL: + case STATUS_INVALID_INFO_CLASS: + case STATUS_INVALID_DEVICE_REQUEST: + case STATUS_INVALID_SYSTEM_SERVICE: + case STATUS_ILLEGAL_INSTRUCTION: + case STATUS_INVALID_LOCK_SEQUENCE: + case STATUS_INVALID_VIEW_SIZE: + case STATUS_INVALID_FILE_FOR_SECTION: + case STATUS_INVALID_DISPOSITION: + case STATUS_INVALID_UNWIND_TARGET: + case STATUS_INVALID_PORT_ATTRIBUTES: + case STATUS_INVALID_PARAMETER_MIX: + case STATUS_OBJECT_NAME_INVALID: + case STATUS_INVALID_VARIANT: + case STATUS_POWER_STATE_INVALID: + case STATUS_INVALID_DEVICE_OBJECT_PARAMETER: + case STATUS_INVALID_BLOCK_LENGTH: + retstat = -EINVAL; + break; +#ifdef ENOMEDIUM + case STATUS_NO_MEDIA_IN_DEVICE: + case STATUS_UNRECOGNIZED_MEDIA: + retstat = -ENOMEDIUM; + break; +#endif + case STATUS_SHARING_VIOLATION: + case STATUS_FILE_LOCK_CONFLICT: + case STATUS_LOCK_NOT_GRANTED: + case STATUS_SHARING_PAUSED: + case STATUS_SHARED_POLICY: + case STATUS_NOT_LOCKED: + case STATUS_PIPE_BUSY: + case STATUS_CONNECTION_IN_USE: + case STATUS_WAIT_FOR_OPLOCK: + retstat = -EBUSY; + break; + case STATUS_LOGON_FAILURE: + case STATUS_ACCOUNT_RESTRICTION: + case STATUS_ILL_FORMED_PASSWORD: + case STATUS_PASSWORD_RESTRICTION: + case STATUS_INVALID_LOGON_HOURS: + case STATUS_INVALID_WORKSTATION: + case STATUS_PASSWORD_EXPIRED: + case STATUS_ACCOUNT_DISABLED: + case STATUS_WRONG_PASSWORD: + case STATUS_SECTION_PROTECTION: + case STATUS_PRIVILEGE_NOT_HELD: + case STATUS_PRIVILEGED_INSTRUCTION: + case STATUS_PASSWORD_MUST_CHANGE: + case STATUS_ACCOUNT_LOCKED_OUT: + case STATUS_RESOURCE_NOT_OWNED: + case STATUS_LICENSE_VIOLATION: + case STATUS_LICENSE_QUOTA_EXCEEDED: + case STATUS_EVALUATION_EXPIRATION: + case STATUS_COPY_PROTECTION_FAILURE: + case STATUS_SMARTCARD_WRONG_PIN: + case STATUS_SMARTCARD_CARD_BLOCKED: + case STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED: + case STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT: + case STATUS_ACCESS_DISABLED_BY_POLICY_PATH: + case STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER: + case STATUS_ACCESS_DISABLED_BY_POLICY_OTHER: + case STATUS_CSS_AUTHENTICATION_FAILURE: + case STATUS_CSS_KEY_NOT_PRESENT: + case STATUS_CSS_KEY_NOT_ESTABLISHED: + case STATUS_INSUFFICIENT_LOGON_INFO: + retstat = -EPERM; + break; + case STATUS_DEVICE_DOES_NOT_EXIST: + case STATUS_DEVICE_NOT_CONNECTED: + case STATUS_DEVICE_POWER_FAILURE: + case STATUS_DEVICE_REMOVED: + case STATUS_PLUGPLAY_NO_DEVICE: + case STATUS_VOLUME_DISMOUNTED: + case STATUS_NOINTERFACE: + case STATUS_PARTITION_FAILURE: + retstat = -ENODEV; + break; + case STATUS_NO_MORE_FILES: + case STATUS_OBJECT_NAME_NOT_FOUND: + case STATUS_NOT_FOUND: + case STATUS_INVALID_PLUGPLAY_DEVICE_PATH: + case STATUS_NO_SUCH_FILE: + case STATUS_NETWORK_NAME_DELETED: + case STATUS_FILE_IS_OFFLINE: + case STATUS_MOUNT_POINT_NOT_RESOLVED: + retstat = -ENOENT; + break; + case STATUS_LOGON_SESSION_EXISTS: + case STATUS_DUPLICATE_NAME: + case STATUS_ALIAS_EXISTS: + case STATUS_ADDRESS_ALREADY_EXISTS: + case STATUS_DUPLICATE_OBJECTID: + case STATUS_OBJECTID_EXISTS: + retstat = -EEXIST; + break; + case STATUS_WRONG_VOLUME: + retstat = -EXDEV; + break; + case STATUS_BUFFER_TOO_SMALL: + case STATUS_SECTION_TOO_BIG: + case STATUS_SYSTEM_HIVE_TOO_LARGE: + retstat = -E2BIG; + break; + case STATUS_MEMORY_NOT_ALLOCATED: + case STATUS_NO_MEMORY: + case STATUS_INSUFFICIENT_RESOURCES: + case STATUS_INSUFF_SERVER_RESOURCES: + retstat = -ENOMEM; + break; + case STATUS_INVALID_HANDLE: + case STATUS_FILE_INVALID: + case STATUS_INVALID_PORT_HANDLE: + case STATUS_FILE_DELETED: + case STATUS_FILE_CLOSED: + case STATUS_FILE_CORRUPT_ERROR: + case STATUS_USER_MAPPED_FILE: + case STATUS_NOT_A_REPARSE_POINT: + case STATUS_DIRECTORY_IS_A_REPARSE_POINT: + case STATUS_FILE_NOT_ENCRYPTED: + case STATUS_FILE_ENCRYPTED: + case STATUS_CORRUPT_SYSTEM_FILE: + case STATUS_HANDLE_NOT_CLOSABLE: + retstat = -EBADF; + break; + case STATUS_FILES_OPEN: + retstat = -EMFILE; + break; + case STATUS_TOO_MANY_OPENED_FILES: + retstat = -ENFILE; + break; + case STATUS_PIPE_NOT_AVAILABLE: + case STATUS_INVALID_PIPE_STATE: + case STATUS_PIPE_BROKEN: + case STATUS_PIPE_EMPTY: + retstat = -EPIPE; + break; + case STATUS_DISK_FULL: + case STATUS_NO_LOG_SPACE: + case STATUS_LOG_FILE_FULL: + case STATUS_NO_SPOOL_SPACE: + case STATUS_PRINT_QUEUE_FULL: + case STATUS_DESTINATION_ELEMENT_FULL: + retstat = -ENOSPC; + break; + case STATUS_MEDIA_WRITE_PROTECTED: + retstat = -EROFS; + break; + case STATUS_DIRECTORY_NOT_EMPTY: + retstat = -ENOTEMPTY; + break; + case STATUS_RETRY: + retstat = -EAGAIN; + break; + case STATUS_OBJECT_PATH_NOT_FOUND: + case STATUS_NOT_A_DIRECTORY: + retstat = -ENOTDIR; + break; + case STATUS_FILE_IS_A_DIRECTORY: + retstat = -EISDIR; + break; + case STATUS_UNEXPECTED_IO_ERROR: + case STATUS_IO_PRIVILEGE_FAILED: + case STATUS_DEVICE_NOT_READY: + case STATUS_IO_DEVICE_ERROR: + case STATUS_OPEN_FAILED: + case STATUS_REPLY_MESSAGE_MISMATCH: + case STATUS_LOST_WRITEBEHIND_DATA: + retstat = -EIO; + break; + case STATUS_NOT_SUPPORTED: + case STATUS_ILLEGAL_FUNCTION: + case STATUS_WMI_NOT_SUPPORTED: + retstat = -EOPNOTSUPP; + break; + case STATUS_PIPE_DISCONNECTED: + case STATUS_CONNECTION_ABORTED: + case STATUS_CONNECTION_DISCONNECTED: + case STATUS_CONNECTION_RESET: + retstat = -ECONNRESET; + break; + default: + break; + } + + return retstat; +} + diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/sound.c posixrdp/posixxrdp.orig/sesman/chansrv/sound.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/chansrv/sound.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/chansrv/sound.c 2010-11-08 09:56:45.000000000 +0100 @@ -17,44 +17,4947 @@ Copyright (C) Jay Sorg 2009 */ +/* #define XRDP_ENABLE_ALSA 1 */ +#define XRDP_ENABLE_PULSEAUDIO 1 + +/* if XRDP_THREADED_PA_MAINLOOP is true, then PulseAudio is run using + * the threaded mainloop model ;(e.g., "pa_threaded_mainloop_start()"); + * otherwise, it is run using the non-threaded mainloop model (e.g., + * by looping "pa_mainloop_iterate()"). + */ +#define XRDP_THREADED_PA_MAINLOOP 1 + +#include +#include +#include +#include +#include +#include +#include +#if defined(__linux__) +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "defines.h" #include "arch.h" #include "parse.h" #include "os_calls.h" +#include "chansrv.h" +#include "devredir_defs.h" +#include "thread_calls.h" +#include "thread_macros.h" +#include "trans.h" +#include "sound_defs.h" +#ifdef XRDP_ENABLE_SOXCONVERT +#include "soxconvert.h" +#endif +#ifdef XRDP_ENABLE_ALSA +#include "alsa.h" +#endif +#include "dbg.h" + +#undef MDBGLOG +#define MDBGLOG(...) (0) + +#if defined(MAX_PDU_LENGTH) +#undef MAX_PDU_LENGTH +#endif +//#define MAX_PDU_LENGTH (MAX_STREAM) +#define MAX_PDU_LENGTH (MAX_STREAM / 2) + +#if !defined(MINVAL) +#define MINVAL(x,y) (((x) > (y)) ? (y) : (x)) +#endif + +typedef struct { + BYTE bSize; + WORD wOutTime; + WORD wAckTime; + WORD wTrueOutTime; + DWORD dwLength; +} pktinfo; + +typedef struct _pkt { + struct _pkt * next; + struct _pkt * prev; + struct stream * s[2]; + unsigned int count; + #define PKT_MAGIC 0xfeefaaf0 + uint32_t magic; + unsigned int byteCount; + double duration; + BYTE cBlockNo; + tc_t lock; +} pkt; + +typedef struct _pktq { + #define MAX_PKTQ 250 + #define SAFE_PKTQ_MIN 50 + #define SAFE_PKTQ_MAX 100 + pkt * head; + int max; + int min; + pkt * items[MAX_PKTQ]; + unsigned int top; + unsigned int bottom; + unsigned int count; + int (*enq)(struct _pktq *, struct _pkt *); + pkt * (*deq)(struct _pktq *); + int (*getCount)(struct _pktq *); + int (*getMax)(struct _pktq *); + int (*setMax)(struct _pktq *, int); + int (*getMin)(struct _pktq *); + int (*setMin)(struct _pktq *, int); + unsigned int (*ready)(struct _pktq *); + void (*__destructor)(struct _pktq *); +} pktq; + + +extern tc_t g_mem_mutex; +extern tc_p mutex_mem; + +static unsigned char g_pktq_locked = 0; +static char g_pktq_holder[32] = ""; +static unsigned char g_pktlog_locked = 0; +static char g_pktlog_holder[32] = ""; + +/* PulseAudio */ +static unsigned char raw = 1; +static pa_mainloop * m = NULL; +static pa_threaded_mainloop * mt = NULL; +static pa_context * context = NULL; +static pa_stream * stream = NULL; +static pa_mainloop_api * mainloop_api = NULL; +static pa_io_event * stdio_event = NULL; +static void * buffer = NULL; +static size_t buffer_length = 0; +static size_t buffer_index = 0; +static char * stream_name = NULL; +static char * client_name = NULL; +static char * device = NULL; +static unsigned char verbose = 0; +static pa_volume_t volume = PA_VOLUME_NORM; +static unsigned char volume_is_set = 0; +static enum {RECORD, PLAYBACK} mode = RECORD; +static pa_channel_map channel_map; +static unsigned char channel_map_set = 0; +static pa_stream_flags_t flags = 0; +static size_t latency = 0; +static size_t process_time = 0; + +#define SPEC_PCM { .format = PA_SAMPLE_S16LE, .rate = 44100, .channels = 2 }; +#define SPEC_ALAW { .format = PA_SAMPLE_ALAW, .rate = 44100, .channels = 2, } +#define SPEC_ULAW { .format = PA_SAMPLE_ULAW, .rate = 44100, .channels = 2, } +#define SPEC_IMA_ADPCM SPEC_PCM + +static pa_sample_spec sample_spec = SPEC_ALAW; +//static pa_sample_spec sample_spec = SPEC_PCM; + +/* threads, mutexes, barriers, and condition variables */ +static tc_t g_cb_mutex; +static tc_p mutex_cb = &g_cb_mutex; + +static tc_t g_init_mutex; +static tc_p mutex_init = &g_init_mutex; +static tc_t g_init_cond; +static tc_p cond_init = (tc_p)NULL; + +static tc_t g_drain_mutex; +static tc_p mutex_drain = &g_drain_mutex; +static tc_t g_drain_cond; +static tc_p cond_drain = (tc_p)(&g_drain_cond); + +static tc_t g_formats_barr; +static tc_p barr_formats = &g_formats_barr; + +static tc_t g_event_mutex; +static tc_p mutex_event = &g_event_mutex; + +static tc_t g_underrun_mutex; +static tc_p mutex_underrun = &g_underrun_mutex; + +static tc_t g_stream_mutex; +static tc_p mutex_stream = &g_stream_mutex; + +static tc_t g_pktq_thread; +static tc_p thread_pktq = (tc_p)NULL; +static tc_t g_thread_mutex; +static tc_p mutex_thread = (tc_p)NULL; + +static tc_t g_ready_cond; +static tc_p cond_ready = (tc_p)NULL; +static tc_t g_ready_mutex; +static tc_p mutex_ready = (tc_p)NULL; + +static tc_t g_stream_ready_cond; +static tc_p cond_stream_ready = (tc_p)NULL; +static tc_t g_stream_ready_mutex; +static tc_p mutex_stream_ready = (tc_p)NULL; + +static tc_t g_rebuilding_cond; +static tc_p cond_rebuilding = (tc_p)(&g_rebuilding_cond); +static tc_t g_rebuilding_mutex; +static tc_p mutex_rebuilding = (tc_p)(&g_rebuilding_mutex); + +static tc_t g_pause_cond; +static tc_p cond_pause = (tc_p)NULL; +static tc_t g_pause_mutex; +static tc_p mutex_pause = (tc_p)NULL; + +static tc_t g_pause_ack_cond; +static tc_p cond_pause_ack = (tc_p)NULL; +static tc_t g_pause_ack_mutex; +static tc_p mutex_pause_ack = (tc_p)NULL; + +static tc_t g_new_mutex; +static tc_p mutex_new = (tc_p)NULL; + +static tc_t g_pa_cond; +static tc_p cond_pa = (tc_p)NULL; + +static tc_t g_buffer_cond; +static tc_p cond_buffer = (tc_p)NULL; +static tc_t g_buffer_mutex; +static tc_p mutex_buffer = (tc_p)NULL; + +static tc_t g_sink_mutex; +static tc_p mutex_sink = (tc_p)(&g_sink_mutex); +static tc_t g_sink_cond; +static tc_p cond_sink = (tc_p)(&g_sink_cond); + +static tc_t g_pa_thread; +static tc_p thread_pa = (tc_p)NULL; +static tc_t g_pa_mutex; +static tc_p mutex_pa = (tc_p)NULL; + +extern tc_t g_out_mutex; +extern tc_p mutex_out; +static tc_t g_sound_mutex; +static tc_p mutex_sound = (tc_p)NULL; +static tc_t g_ins_mutex; +static tc_p mutex_ins = (tc_p)NULL; +static tc_t g_pktq_mutex; +static tc_p mutex_pktq = (tc_p)NULL; +static tc_t g_audio_mutex; +static tc_p mutex_audio = (tc_p)NULL; + +static tc_t g_up_mutex; +static tc_p mutex_up = (tc_p)NULL; +static tc_t g_close_mutex; +static tc_p mutex_close = (tc_p)NULL; +static tc_t g_close_rw; +static tc_p rw_close = (tc_p)NULL; +static tc_t g_pktlog_mutex; +static tc_p mutex_pktlog = (tc_p)NULL; +static tc_t g_pktready_mutex; +static tc_p mutex_pktready = (tc_p)NULL; +static tc_t g_train_mutex; +static tc_p mutex_train = (tc_p)NULL; +static tc_t g_send_mutex; +static tc_p mutex_send = (tc_p)NULL; +static tc_t g_socket_mutex; +static tc_p mutex_socket = (tc_p)NULL; +static tc_t g_prev_mutex; +static tc_p mutex_prev = (tc_p)NULL; +static tc_t g_formats_mutex; +static tc_p mutex_formats = (tc_p)NULL; +static tc_t g_block_mutex; +static tc_p mutex_block = (tc_p)NULL; + +static tc_t mutex_attribute; +static tc_p g_attr = (tc_p)NULL; + +static char g_hopper[MAX_STREAM]; +static size_t g_hopper_index = 0; +static size_t g_hopper_length = 0; + +#define MAX_PKTLOG 2048 +static char selfpipe_path[512]; +static pktinfo pktlog[MAX_PKTLOG]; +static unsigned int g_is_child = 0; +static int g_sink_index = -1; +static volatile unsigned char g_sink_input_count = 0; +static volatile unsigned int g_ready_waiting = 0; +static volatile unsigned int g_ready_count = 0; +static volatile int g_ready_playbytes = 0; +static volatile int g_ready_playtime = 0; +//static unsigned int g_preferred_wave_format = WAVE_FORMAT_PCM; +//static unsigned int g_preferred_wave_format = WAVE_FORMAT_IMA_ADPCM; +static unsigned int g_preferred_wave_format = WAVE_FORMAT_ALAW; +//static unsigned int g_preferred_wave_format = WAVE_FORMAT_MULAW; +static volatile unsigned int g_trained = 0; +static volatile unsigned int g_received_close_pdu = 0; +static unsigned int g_callee_frees = 1; +static volatile unsigned int g_sound_up = 0; +static unsigned int g_ready_triggered = 0; +static unsigned int g_ready_triggered_count = 0; +static volatile int g_client_format_index = -1; +static volatile WORD g_client_format = 0x0000; +static int g_client_format_count = 0; +static volatile unsigned int g_sound_ready_to_train = 0; +static volatile unsigned int g_sound_ready_to_send = 0; +static volatile unsigned char g_drain = 0; +static unsigned int g_current_block = 0x01; +static double g_prev_rtime = 0.; +static double g_prev_duration = 0.; +static double g_diff = 0.; +static int g_format_byte_rate = 0; +static volatile unsigned int g_latency = 0; + + +//static unsigned int g_target_latency = 800; /* in milliseconds */ +//static unsigned int g_high_latency = 1200; /* in milliseconds */ +//static unsigned int g_max_latency = 1600; /* in milliseconds */ +//static unsigned int g_low_latency = 600; /* in milliseconds */ +//static unsigned int g_lower_latency = 400; /* in milliseconds */ +//static unsigned int g_min_latency = 300; /* in milliseconds */ + +static unsigned int g_target_latency = 500; /* in milliseconds */ +static unsigned int g_high_latency = 700; /* in milliseconds */ +static unsigned int g_max_latency = 800; /* in milliseconds */ +static unsigned int g_low_latency = 330; /* in milliseconds */ +static unsigned int g_lower_latency = 220; /* in milliseconds */ +static unsigned int g_min_latency = 150; /* in milliseconds */ + +static volatile unsigned int g_underruns = 0; /* buffer underrun counter */ +static long int g_most_recent_underrun_timestamp = 0; +static volatile unsigned char g_initialized = 0; +static volatile unsigned char g_stream_ready = 0; +static volatile unsigned char g_pa_ready = 0; +static volatile int g_outstanding = 0; +static volatile int g_outstanding_playtime = 200; +static volatile int g_outstanding_playbytes = 44100 / 5; +static volatile int g_client_formats_received = 0; +static volatile int g_idle = 0; +static unsigned char g_pause = 0; +static unsigned char g_paused = 0; +static unsigned char g_pause_acked = 0; +static volatile unsigned char g_sink_query_waiting = 0; +static unsigned char g_enable_skew_compensation = 1; +static unsigned char g_drop_silence = 1; +static volatile unsigned int g_thunk = 0; +static volatile unsigned char g_rebuilding = 0; + +static tbus g_sound_socket = -1; +static tbus g_sound_wait_obj = -1; +static tbus g_sound_selfpipe = -1; +static tbus g_fd = 0; + +static const unsigned int g_audio_socket_type = WO_FIFO; /* 1: PF_INET/PF_INET6; 2: PF_UNIX; 3: FIFO (named pipe) */ + +static pktq * g_pktq = (pktq *)NULL; +static struct stream * g_ins = NULL; +static SERVER_AUDIO_VERSION_AND_FORMATS * server_formats = NULL; +static CLIENT_AUDIO_VERSION_AND_FORMATS * client_formats = NULL; +static struct trans * g_audio = (struct trans *)NULL; + +static int APP_CC reset_pktq(pktq *); + +int APP_CC sound_deinit(void); +static char * APP_CC get_audio_socket(const char *); +static size_t APP_CC sound_queue_packet(void *, size_t); +static int APP_CC sound_estimate_latency(void); +static void * APP_CC sound_pktq_loop(void *); +static void * APP_CC sound_pa_start(void *); +static void * APP_CC sound_timer_loop(void *); +static int APP_CC sound_get_pulseaudio_server(const char **); + +static void APP_CC pa_exit_signal_callback(pa_mainloop_api *, pa_signal_event *, int, void *); + +static void APP_CC start_drain_noquit(void); + +static int APP_CC q_enq(pktq *, pkt *); +static int APP_CC q_enq_old3(pktq *, pkt *); +static pkt * APP_CC q_deq(pktq *); +static pkt * APP_CC q_deq_old3(pktq *); +static int APP_CC q_getCount(pktq *); +static int APP_CC q_getMax(pktq *); +static int APP_CC q_setMax(pktq *, int); +static int APP_CC q_getMin(pktq *); +static int APP_CC q_setMin(pktq *, int); +static unsigned int APP_CC q_ready(pktq *); +static void APP_CC destroy_pktq(pktq *); + + +static void APP_CC do_stream_write(size_t); +static void APP_CC stdin_callback(pa_mainloop_api *, pa_io_event *, int, pa_io_event_flags_t, void *); +static void APP_CC stdout_callback(pa_mainloop_api *, pa_io_event *, int, pa_io_event_flags_t f, void *); +static void APP_CC stream_read_callback(pa_stream *, size_t, void *); +static void APP_CC stream_write_callback(pa_stream *, size_t, void *); +static void APP_CC stream_suspended_callback(pa_stream *, void *); +static void APP_CC stream_underflow_callback(pa_stream *, void *); +static void APP_CC stream_overflow_callback(pa_stream *, void *); +static void APP_CC stream_buffer_attr_callback(pa_stream *, void *); +static void APP_CC stream_event_callback(pa_stream *, const char *, pa_proplist *, void *); +static void APP_CC context_state_callback(pa_context *, void *); +static void APP_CC pa_quit(int); + +static void APP_CC pa_subscribe_cb(struct pa_context *, enum pa_subscription_event_type, uint32_t, void *); +static void APP_CC pa_context_success_cb(pa_context *, int, void *); +static void APP_CC pa_stream_latency_update_cb(pa_stream *, void *); +static void APP_CC pa_sink_input_info_cb(pa_context *, const pa_sink_input_info *, int, void *); + +extern int g_rdpsnd_chan_id; /* in chansrv.c */ + +#if defined(XRDP_ENABLE_ALSA) +extern alsa * g_alsa; +#endif -extern int g_rdpsnd_chan_id; /* in chansrv.c */ /*****************************************************************************/ -int APP_CC -sound_init(void) +/* returns time in milliseconds + this is like g_time2 in os_calls, but not milliseconds since machine was + up, something else + this is a time value similar to what the xserver uses */ +static uint16_t APP_CC +sound_get_local_time(void) { + uint16_t rv = 0; + //return g_time3(); + rv = (uint16_t)(((double)(g_time2()) / (double)(CLOCKS_PER_SEC)) * 1000); + //MDBGLOG("sound","INFO\t[%s()]: done (rv = %d).",__func__,rv); + return rv; +} + +/*****************************************************************************/ +static int APP_CC +sound_audioformat_from_name(WAVEFORMATEX ** ifmt, const char * FormatName) { + size_t len = sizeof(WAVEFORMATEX); + WAVEFORMATEX * afmt = (WAVEFORMATEX *)NULL; + char tbuf[256]; + MPEGLAYER3WAVEFORMAT mp3; + BYTE * b = (BYTE *)NULL; + g_memset(&mp3, 0x00, sizeof(MPEGLAYER3WAVEFORMAT)); + if (ifmt != NULL) { + afmt = *ifmt; + } + if (afmt == NULL) { + afmt = (WAVEFORMATEX *)g_malloc(sizeof(WAVEFORMATEX) + ADPCM_WFX_EXTRA_BYTES + 4, 1); + } + if (afmt == NULL) { + MDBGLOG("sound","ERROR\t[%s()]: afmt is NULL",__func__); + return 1; + } + afmt->wFormatTag = XRDP_DEFAULT_WAVE_FORMAT; /* default: PCM */ + afmt->nChannels = 0x0002; /* default: 2 channels */ + afmt->nSamplesPerSec = 0x00005622; /* default: 0x5622 = 22050 kHz */ + afmt->nAvgBytesPerSec = 0x00015888; /* = nSamplesPerSec * nBlockAlign = 0x15888 = 88200 */ + afmt->nBlockAlign = 0x0004; /* if wFormatTag is WAVE_FORMAT_PCM or WAVE_FORMAT_EXTENSIBLE, nBlockAlign must be equal to the product of nChannels and wBitsPerSample divided by 8 (bits per byte) */ + afmt->wBitsPerSample = 0x0010; /* if wFormatTag is WAVE_FORMAT_PCM, then wBitsPerSample should be equal to 8 or 16 */ + afmt->cbSize = 0x0000; /* size, in bytes, of extra format information appended to the end of the WAVEFORMATEX structure */ + //afmt->data = NULL; /* no extra information for default (PCM) */ + if (FormatName == NULL || g_strlen(FormatName) == 0 || !g_strncmp(FormatName,"PCM",g_strlen(FormatName)) || !g_strncmp(FormatName,"pcm",g_strlen(FormatName))) { + afmt->wFormatTag = WAVE_FORMAT_PCM; + } + else if (!g_strncmp(FormatName,"ADPCM",g_strlen(FormatName)) || !g_strncmp(FormatName,"adpcm",g_strlen(FormatName))) { + afmt->wFormatTag = WAVE_FORMAT_ADPCM; + afmt->nChannels = 0x0002; + afmt->nSamplesPerSec = 0x00005622; /* = 22050Hz */ + afmt->nAvgBytesPerSec = 0x00005727; /* = 22311Hz */ + afmt->nBlockAlign = 0x0400; + afmt->wBitsPerSample = 0x0004; + afmt->cbSize = ADPCM_WFX_EXTRA_BYTES; + //afmt->data = (BYTE *)g_malloc(sizeof(BYTE) * afmt->cbSize,1); + afmt->data[0] = 0xf4; + afmt->data[1] = 0x03; + afmt->data[2] = 0x07; + afmt->data[3] = 0x00; + afmt->data[4] = 0x00; + afmt->data[5] = 0x01; + afmt->data[6] = 0x00; + afmt->data[7] = 0x00; + afmt->data[8] = 0x00; + afmt->data[9] = 0x02; + afmt->data[10] = 0x00; + afmt->data[11] = 0xff; + afmt->data[12] = 0x00; + afmt->data[13] = 0x00; + afmt->data[14] = 0x00; + afmt->data[15] = 0x00; + afmt->data[16] = 0xc0; + afmt->data[17] = 0x00; + afmt->data[18] = 0x40; + afmt->data[19] = 0x00; + afmt->data[20] = 0xf0; + afmt->data[21] = 0x00; + afmt->data[22] = 0x00; + afmt->data[23] = 0x00; + afmt->data[24] = 0xcc; + afmt->data[25] = 0x01; + afmt->data[26] = 0x30; + afmt->data[27] = 0xff; + afmt->data[28] = 0x88; + afmt->data[29] = 0x01; + afmt->data[30] = 0x18; + afmt->data[31] = 0xff; + } + else if (!g_strncmp(FormatName,"IMA",g_strlen(FormatName)) || !g_strncmp(FormatName,"ima",g_strlen(FormatName)) || !g_strncmp(FormatName,"IMA_ADPCM",g_strlen(FormatName)) || !g_strncmp(FormatName,"IMA ADPCM",g_strlen(FormatName)) || !g_strncmp(FormatName,"ima_adpcm",g_strlen(FormatName)) || !g_strncmp(FormatName,"ima adpcm",g_strlen(FormatName))) { + afmt->wFormatTag = WAVE_FORMAT_IMA_ADPCM; + afmt->nChannels = 0x0002; + afmt->nSamplesPerSec = 0x00005622; /* = 22050Hz */ + afmt->nAvgBytesPerSec = 0x000056b9; /* = 22201Hz */ + afmt->nBlockAlign = 0x0400; + afmt->wBitsPerSample = 0x0004; + afmt->cbSize = 0x0002; + afmt->data[0] = 0xf9; + afmt->data[1] = 0x03; + } + else if (!g_strncmp(FormatName,"MP3",g_strlen(FormatName)) || !g_strncmp(FormatName,"mp3",g_strlen(FormatName)) || !g_strncmp(FormatName,"MPEGLAYER3",g_strlen(FormatName))) { + mp3.wID = MPEGLAYER3_ID_MPEG; + mp3.fdwFlags = MPEGLAYER3_FLAG_PADDING_OFF; + //mp3.nBlockSize = MPEGLAYER3_NBLOCKSIZE; + mp3.nBlockSize = 313; + mp3.nFramesPerBlock = MPEGLAYER3_NFRAMESPERBLOCK; + mp3.nCodecDelay = MPEGLAYER3_NCODECDELAY; + afmt->wFormatTag = WAVE_FORMAT_MPEGLAYER3; + afmt->nChannels = 0x0002; + //afmt->nSamplesPerSec = 0x00005622; + afmt->nSamplesPerSec = 44100; + //afmt->nAvgBytesPerSec = 128 * (1024 / 8); + afmt->nAvgBytesPerSec = 176400; + //afmt->wBitsPerSample = 0x0000; + afmt->wBitsPerSample = 16; + afmt->nBlockAlign = 4; + afmt->cbSize = MPEGLAYER3_WFX_EXTRA_BYTES; + b = (BYTE *)(&mp3); + afmt->data[0] = b[1]; + afmt->data[1] = b[0]; + afmt->data[2] = b[3]; + afmt->data[3] = b[2]; + afmt->data[4] = b[5]; + afmt->data[5] = b[4]; + afmt->data[6] = b[7]; + afmt->data[7] = b[6]; + afmt->data[8] = b[9]; + afmt->data[9] = b[8]; + afmt->data[10] = b[11]; + afmt->data[11] = b[10]; + } + else if (!g_strncmp(FormatName,"ULAW",g_strlen(FormatName)) || !g_strncmp(FormatName,"ulaw",g_strlen(FormatName)) || !g_strncmp(FormatName,"MULAW",g_strlen(FormatName)) || !g_strncmp(FormatName,"mulaw",g_strlen(FormatName)) || !g_strncmp(FormatName,"AU",g_strlen(FormatName)) || !g_strncmp(FormatName,"au",g_strlen(FormatName))) { + afmt->wFormatTag = WAVE_FORMAT_MULAW; + afmt->nChannels = 0x0002; + afmt->nSamplesPerSec = 0x00005622 * afmt->nChannels; /* = 22050Hz * nChannels */ + afmt->nAvgBytesPerSec = 0x0000ac44 * afmt->nChannels; /* = 22201Hz * nChannels */ + afmt->nBlockAlign = 0x0002; + afmt->wBitsPerSample = 0x0008; + afmt->cbSize = 0x0000; + } + else if (!g_strncmp(FormatName,"ALAW",g_strlen(FormatName)) || !g_strncmp(FormatName,"alaw",g_strlen(FormatName))) { + afmt->wFormatTag = WAVE_FORMAT_ALAW; + afmt->nChannels = 0x0002; + afmt->nSamplesPerSec = 0x00005622 * afmt->nChannels; + afmt->nAvgBytesPerSec = 0x0000ac44 * afmt->nChannels; + afmt->nBlockAlign = 0x0002; + afmt->wBitsPerSample = 0x0008; + afmt->cbSize = 0x0000; + } + else if (!g_strncmp(FormatName,"MSG723",g_strlen("MSG723")) || !g_strncmp(FormatName,"msg723",g_strlen("msg723"))) { + afmt->wFormatTag = WAVE_FORMAT_MSG723; + } + else if (!g_strncmp(FormatName,"GSM610",g_strlen(FormatName)) || !g_strncmp(FormatName,"gsm610",g_strlen(FormatName)) || !g_strncmp(FormatName,"GSM",g_strlen(FormatName)) || !g_strncmp(FormatName,"gsm",g_strlen(FormatName))) { + afmt->wFormatTag = WAVE_FORMAT_GSM610; + afmt->nChannels = 0x0001; + afmt->nSamplesPerSec = 0x00005622; + afmt->nAvgBytesPerSec = 0x0000117e; + afmt->nBlockAlign = 0x0041; + afmt->wBitsPerSample = 0x0000; + afmt->cbSize = 0x0002; + afmt->data[0] = 0x40; + afmt->data[1] = 0x01; + } + else if (!g_strncmp(FormatName,"HIGSM610",g_strlen(FormatName)) || !g_strncmp(FormatName,"higsm610",g_strlen(FormatName)) || !g_strncmp(FormatName,"HIGSM",g_strlen(FormatName)) || !g_strncmp(FormatName,"higsm",g_strlen(FormatName))) { + afmt->wFormatTag = WAVE_FORMAT_GSM610; + afmt->nChannels = 0x0001; + afmt->nSamplesPerSec = 0x0000ac44; + afmt->nAvgBytesPerSec = 0x000022fd; + afmt->nBlockAlign = 0x0041; + afmt->wBitsPerSample = 0x0000; + afmt->cbSize = 0x0002; + afmt->data[0] = 0x40; + afmt->data[1] = 0x01; + } + else if (!g_strncmp(FormatName,"HIPCM",g_strlen("HIPCM")) || !g_strncmp(FormatName,"hipcm",g_strlen("hipcm"))) { + afmt->wFormatTag = WAVE_FORMAT_PCM; + afmt->nChannels = 0x0002; + afmt->nSamplesPerSec = 44100; + afmt->nAvgBytesPerSec = 0x0002B110; + afmt->nBlockAlign = 0x0004; + afmt->wBitsPerSample = 0x0010; + afmt->cbSize = 0x0000; + //afmt->data = NULL; + } + else { + afmt->wFormatTag = WAVE_FORMAT_UNKNOWN; + } + if (ifmt != NULL && afmt != NULL && afmt != *ifmt) { + WAVEFORMATEX * ofmt = (WAVEFORMATEX *)NULL; + len += afmt->cbSize; + if (len > 0) { + ofmt = (WAVEFORMATEX *)g_realloc(afmt, len + 4); + } + else { + ofmt = afmt; + } + *ifmt = ofmt; + } return 0; } /*****************************************************************************/ -int APP_CC -sound_deinit(void) -{ +static int APP_CC +sound_AUDIO_FORMAT_out(struct stream* s, AUDIO_FORMAT *afmt) { + int rv = 0; + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + if (s == NULL || afmt == NULL) { + rv = -1; + goto end; + } + + out_uint16_le(s, afmt->wFormatTag); + out_uint16_le(s, afmt->nChannels); + out_uint32_le(s, afmt->nSamplesPerSec); + out_uint32_le(s, afmt->nAvgBytesPerSec); + out_uint16_le(s, afmt->nBlockAlign); + out_uint16_le(s, afmt->wBitsPerSample); + out_uint16_le(s, afmt->cbSize); + if (afmt->cbSize > 0) { + out_uint8a(s, afmt->data, afmt->cbSize); + } + + end:; + return rv; +} + +/*****************************************************************************/ +static int APP_CC +sound_AUDIO_FORMAT_in(struct stream * s, AUDIO_FORMAT ** ifmt) { + AUDIO_FORMAT * afmt = (AUDIO_FORMAT *)NULL; + AUDIO_FORMAT * ofmt = (AUDIO_FORMAT *)NULL; + size_t len = 0; + uint16_t idx; + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + if (ifmt == NULL) { + MDBGLOG("sound","ERROR\t[%s()]: ifmt is NULL",__func__); + } + else { + afmt = (AUDIO_FORMAT *)g_malloc((sizeof(AUDIO_FORMAT) + 32) + 4, 1); + in_uint16_le(s, afmt->wFormatTag); + in_uint16_le(s, afmt->nChannels); + in_uint32_le(s, afmt->nSamplesPerSec); + in_uint32_le(s, afmt->nAvgBytesPerSec); + in_uint16_le(s, afmt->nBlockAlign); + in_uint16_le(s, afmt->wBitsPerSample); + in_uint16_le(s, afmt->cbSize); + if (afmt->cbSize > 0) { + in_uint8a(s, afmt->data, MIN(afmt->cbSize,32)); + } + len = sizeof(AUDIO_FORMAT) + afmt->cbSize + 4; + if (len > (sizeof(AUDIO_FORMAT) + 32)) { + ofmt = (AUDIO_FORMAT *)g_realloc(afmt, len); + } + else { + ofmt = afmt; + } + *ifmt = ofmt; + } + return 0; } /*****************************************************************************/ -int APP_CC -sound_data_in(struct stream* s, int chan_id, int chan_flags, int length, - int total_length) -{ +static int APP_CC +sound_SNDPROLOG_in(struct stream* s, SNDPROLOG *hdr) { + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + in_uint8(s, hdr->msgType); + in_uint8(s, hdr->bPad); + in_uint16_le(s, hdr->BodySize); return 0; } /*****************************************************************************/ -int APP_CC -sound_get_wait_objs(tbus* objs, int* count, int* timeout) -{ +static int APP_CC +sound_process_SNDC_QUALITYMODE(struct stream* s, SNDPROLOG *hdr, QUALITY_MODE *pdu) { + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + if (g_callee_frees && pdu != NULL) { + SOUND_FREE(pdu); + } + return 0; } /*****************************************************************************/ -int APP_CC -sound_check_wait_objs(void) -{ +static int APP_CC +sound_process_SNDC_FORMATS(struct stream* s, SNDPROLOG *hdr, CLIENT_AUDIO_VERSION_AND_FORMATS * pdu) { + int rv = 0; + unsigned int idx = 0; + unsigned int lmt = 0; + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + if (pdu == NULL || s == NULL || hdr == NULL) { + rv = -1; + goto end; + } + + pdu->Header.msgType = hdr->msgType; + pdu->Header.bPad = hdr->bPad; + pdu->Header.BodySize = hdr->BodySize; + in_uint32_le(s, pdu->dwFlags); + in_uint32_le(s, pdu->dwVolume); + in_uint32_le(s, pdu->dwPitch); + in_uint16_le(s, pdu->wDGramPort); + in_uint16_le(s, pdu->wNumberOfFormats); + in_uint8(s, pdu->cLastBlockConfirmed); + in_uint16_le(s, pdu->wVersion); + in_uint8(s, pdu->bPad); + + lmt = pdu->wNumberOfFormats; + pdu->sndFormats = (AUDIO_FORMAT **)g_malloc(sizeof(AUDIO_FORMAT *) * lmt, 1); + for (idx = 0; idx < lmt; idx++) { + sound_AUDIO_FORMAT_in(s, &(pdu->sndFormats[idx])); + } + + end:; + if (g_callee_frees && pdu != NULL) { + SOUND_FREE(pdu); + } + return rv; +} + +/*****************************************************************************/ +static int APP_CC +sound_process_SNDC_CLOSE(struct stream* s, SNDPROLOG *hdr) { + int rv = 0; + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + TC_MUTEX_LOCK(mutex_close); + g_received_close_pdu = 1; + TC_MUTEX_UNLOCK(mutex_close); + TC_MUTEX_LOCK(mutex_sound); + TC_MUTEX_LOCK(mutex_ready); + if (g_ready_waiting > 0) { + if (g_ready_waiting > 1) { + TC_COND_BROADCAST(cond_ready); + } + else { + TC_COND_SIGNAL(cond_ready); + } + } + TC_MUTEX_UNLOCK(mutex_ready); + TC_MUTEX_LOCK(mutex_pa); + TC_COND_BROADCAST(cond_pa); + TC_MUTEX_UNLOCK(mutex_pa); + sound_deinit(); + TC_MUTEX_UNLOCK(mutex_sound); + + end:; + return rv; +} + +/*****************************************************************************/ +static int APP_CC +sound_process_SNDC_WAVECONFIRM(struct stream * s, SNDPROLOG * hdr, SNDWAV_CONFIRM * pdu) { + int rv = 0; + int dwlen = 0; + uint32_t lat = 0; + pktinfo tinfo; + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + g_memset(&tinfo,0,sizeof(pktinfo)); + + if (s == NULL || pdu == NULL) { + MDBGLOG("sound","ERROR\t[%s()]: NULL pointer (s = %p, pdu = %p)",__func__,s,pdu); + rv = -1; + goto end; + } + + in_uint16_le(s, pdu->wTimeStamp); + in_uint8(s, pdu->cConfirmedBlockNo); + in_uint8(s, pdu->bPad); + + { + MB; + TC_MUTEX_LOCK(mutex_pktlog); + if (pdu->cConfirmedBlockNo < MAX_PKTLOG && pktlog[(pdu->cConfirmedBlockNo)].wOutTime > 0) { + pktlog[(pdu->cConfirmedBlockNo)].wAckTime = pdu->wTimeStamp; + lat = g_latency = (pktlog[(pdu->cConfirmedBlockNo)].wAckTime > pktlog[(pdu->cConfirmedBlockNo)].wOutTime) ? pktlog[(pdu->cConfirmedBlockNo)].wAckTime - pktlog[(pdu->cConfirmedBlockNo)].wOutTime : (65536 - pktlog[(pdu->cConfirmedBlockNo)].wOutTime) + pktlog[(pdu->cConfirmedBlockNo)].wAckTime; + if (g_outstanding > 0) { + g_outstanding--; + } + else { + g_thunk++; + } + g_outstanding_playbytes -= pktlog[(pdu->cConfirmedBlockNo)].dwLength; + g_outstanding_playtime = (g_outstanding_playbytes > 0) ? pa_bytes_to_usec(g_outstanding_playbytes, &sample_spec) / PA_USEC_PER_MSEC : 0; + g_outstanding_playtime *= 1; + g_memcpy(&tinfo,&(pktlog[(pdu->cConfirmedBlockNo)]),sizeof(pktinfo)); + g_memset(&(pktlog[(pdu->cConfirmedBlockNo)]),0,sizeof(pktinfo)); + } + TC_MUTEX_LOCK(mutex_ready); + if (g_ready_playtime > g_high_latency) { + TC_MUTEX_UNLOCK(mutex_ready); + TC_MUTEX_LOCK(mutex_pktq); + if (g_pktq != NULL && g_pktq->count > 0) { + reset_pktq(g_pktq); + } + TC_MUTEX_UNLOCK(mutex_pktq); + } + else { + TC_MUTEX_UNLOCK(mutex_ready); + } + TC_MUTEX_UNLOCK(mutex_pktlog); + } + + end:; + if (1 || (verbose && pdu != NULL)) { + MDBGLOG("sound","INFO\t[%s()]: <<>> ",__func__); + MDBGLOG("sound","\t*\tg_outstanding = %d; g_ready_count = %d; g_latency = %d",g_outstanding,g_ready_count,lat); + MDBGLOG("sound","\t*\tcConfirmedBlockNo = %d; wTimeStamp (wAckTime) = %d",pdu->cConfirmedBlockNo,pdu->wTimeStamp); + MDBGLOG("sound","\t*\tpktlog->wOutTime = %d; pktlog->wTrueOutTime = %d; pktlog->dwLength = %d",tinfo.wOutTime,tinfo.wTrueOutTime,tinfo.dwLength); + MDBGLOG("sound","\t*\tg_outstanding_playbytes = %d; g_outstanding_playtime = %d\n",g_outstanding_playbytes,g_outstanding_playtime); + } + if (g_callee_frees && pdu != NULL) { + if (pdu->__destructor != NULL) { + pdu->__destructor(pdu); + } + else { + g_free(pdu); + } + pdu = NULL; + } + return rv; +} + +/*****************************************************************************/ +static int APP_CC +sound_process_SNDC_TRAININGCONFIRM(struct stream * s, SNDPROLOG * hdr, SNDTRAININGCONFIRM * pdu) { + int rv = 0; + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + if (pdu == NULL || s == NULL || hdr == NULL) { + rv = -1; + goto end; + } + + pdu->Header.msgType = hdr->msgType; + pdu->Header.bPad = hdr->bPad; + pdu->Header.BodySize = hdr->BodySize; + + in_uint16_le(s, pdu->wTimeStamp); + in_uint16_le(s, pdu->wPackSize); + + end:; + if (g_callee_frees && pdu != NULL) { + SOUND_FREE(pdu); + } + return rv; +} + +/*****************************************************************************/ +static void APP_CC +destroy_SNDWAV(void *pdu) { + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + if (pdu != NULL) { + if (((SNDWAV *)pdu)->Data != NULL) { + g_free(((SNDWAV *)pdu)->Data); + } + g_free((SNDWAV *)pdu); + } +} + +/*****************************************************************************/ +static void APP_CC +destroy_SNDCLOSE(void *pdu) { + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + //g_free((SNDCLOSE *)pdu); +} + +/*****************************************************************************/ +static void APP_CC +destroy_AUDIO_FORMAT(void *pdu) { + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + //g_free(((AUDIO_FORMAT *)pdu)->data); + //g_free((AUDIO_FORMAT *)pdu); +} + +/*****************************************************************************/ +static void APP_CC +destroy_SNDWAVINFO(void *pdu) { + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + if ((((SNDWAVINFO *)pdu)->appendix != NULL) && (((SNDWAVINFO *)pdu)->alen > 0)) { + if ( ((SNDWAV *)(((SNDWAVINFO *)pdu)->appendix))->__destructor != NULL ) { + (*((SNDWAV *)(((SNDWAVINFO *)pdu)->appendix))->__destructor)((void *)((SNDWAVINFO *)pdu)->appendix); + } + g_free((SNDWAVINFO *)pdu); + } +} + +/*****************************************************************************/ +static void APP_CC +destroy_SNDWAV_CONFIRM(void *pdu) { + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + if (pdu != NULL) { + g_free((SNDWAV_CONFIRM *)pdu); + } +} + +/*****************************************************************************/ +static void APP_CC +destroy_SNDTRAINING(void *pdu) { + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + if (pdu != NULL) { + if (((SNDTRAINING *)pdu)->data != NULL) { + g_free(((SNDTRAINING *)pdu)->data); + ((SNDTRAINING *)pdu)->data = NULL; + } + g_free((SNDTRAINING *)pdu); + } +} + +/*****************************************************************************/ +static void APP_CC +destroy_SNDTRAININGCONFIRM(void *pdu) { + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + if (pdu != NULL) { + g_free((SNDTRAININGCONFIRM *)pdu); + } +} + +/*****************************************************************************/ +static void APP_CC +destroy_CLIENT_AUDIO_VERSION_AND_FORMATS(void *pdu) { + unsigned int idx = 0; + unsigned int lmt = 0; + CLIENT_AUDIO_VERSION_AND_FORMATS *tmp = NULL; + AUDIO_FORMAT *cval = NULL; + + tmp = (CLIENT_AUDIO_VERSION_AND_FORMATS *)pdu; + if (tmp != NULL) { + lmt = tmp->wNumberOfFormats; + if (tmp->sndFormats != NULL) { + /* + for (idx = 0; idx < lmt; idx++) { + cval = (AUDIO_FORMAT *)tmp->sndFormats[idx]; + if (cval != NULL) { + if ( (*cval->__destructor) != NULL ) { + (*cval->__destructor)((void *)cval); + } + } + } + */ + } + //g_free(tmp); + } +} + +/*****************************************************************************/ +static void APP_CC +destroy_SERVER_AUDIO_VERSION_AND_FORMATS(void *pdu) { + if (pdu != NULL) { + destroy_CLIENT_AUDIO_VERSION_AND_FORMATS(pdu); + } +} + +/*****************************************************************************/ +static void APP_CC +destroy_QUALITY_MODE(void *pdu) { + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + if (pdu != NULL) { + g_free((QUALITY_MODE *)pdu); + } +} + +/*****************************************************************************/ +static int APP_CC +construct_AUDIO_FORMAT(AUDIO_FORMAT * pdu) { + pdu->__destructor = &destroy_AUDIO_FORMAT; + return 0; +} + +static AUDIO_FORMAT * APP_CC +create_AUDIO_FORMAT() { + AUDIO_FORMAT *pdu = NULL; + pdu = (AUDIO_FORMAT *)g_malloc(sizeof(AUDIO_FORMAT),1); + pdu->__destructor = &destroy_AUDIO_FORMAT; + return pdu; +} + + +/*****************************************************************************/ +static int APP_CC +construct_pktq(pktq * self) { + int rv = 0; + if (self == NULL) { + rv = -1; + goto end; + } + self->enq = &q_enq; + self->deq = &q_deq; + self->getCount = &q_getCount; + self->getMax = &q_getMax; + self->setMax = &q_setMax; + self->getMin = &q_getMin; + self->setMin = &q_setMin; + self->ready = &q_ready; + self->__destructor = &destroy_pktq; + self->setMax(self,SAFE_PKTQ_MAX); + self->setMin(self,SAFE_PKTQ_MIN); + g_memset(self->items,0,(MAX_PKTQ * sizeof(size_t))); + self->top = 0; + self->bottom = 0; + self->head = NULL; + self->count = 0; + TC_MUTEX_LOCK(mutex_ready); + g_ready_count = 0; + g_ready_playbytes = 0; + g_ready_playtime = 0; + TC_MUTEX_UNLOCK(mutex_ready); + /* + TC_MUTEX_LOCK(mutex_pktlog); + g_outstanding = 0; + g_outstanding_playbytes = 0; + g_outstanding_playtime = 0; + TC_MUTEX_UNLOCK(mutex_pktlog); + */ + end:; + return rv; +} + +/*****************************************************************************/ +static int APP_CC +reset_pktq(pktq * self) { + int rv = 0; + if (self == NULL) { + rv = -1; + goto end; + } + self->enq = &q_enq; + self->deq = &q_deq; + self->getCount = &q_getCount; + self->getMax = &q_getMax; + self->setMax = &q_setMax; + self->getMin = &q_getMin; + self->setMin = &q_setMin; + self->ready = &q_ready; + self->__destructor = &destroy_pktq; + if (self->count > 0 && self->deq != NULL) { + pkt * packet = (pkt *)NULL; + unsigned int idx = 0; + for (idx = 0; idx < self->count; idx++) { + packet = self->deq(self); + if (packet != NULL) { + //TC_MUTEX_LOCK(&(packet->lock)); + if (packet->s[0] != NULL) { + free_stream(packet->s[0]); + } + if (packet->s[1] != NULL) { + free_stream(packet->s[1]); + } + packet->s[0] = NULL; + packet->s[1] = NULL; + //TC_MUTEX_UNLOCK(&(packet->lock)); + g_free(packet); + packet = NULL; + } + } + } + self->setMax(self,SAFE_PKTQ_MAX); + self->setMin(self,SAFE_PKTQ_MIN); + g_memset(self->items,0,(MAX_PKTQ * sizeof(size_t))); + self->top = 0; + self->bottom = 0; + self->head = NULL; + self->count = 0; + TC_MUTEX_LOCK(mutex_ready); + g_ready_count = 0; + g_ready_playbytes = 0; + g_ready_playtime = 0; + TC_MUTEX_UNLOCK(mutex_ready); + end:; + return rv; +} + +/*****************************************************************************/ +static int APP_CC +construct_SNDWAV_CONFIRM(SNDWAV_CONFIRM *pdu) { + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + pdu->__destructor = &destroy_SNDWAV_CONFIRM; + + return 0; +} + +/*****************************************************************************/ +static int APP_CC +construct_SNDTRAININGCONFIRM(SNDTRAININGCONFIRM *pdu) { + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + pdu->__destructor = &destroy_SNDTRAININGCONFIRM; + + return 0; +} + +/*****************************************************************************/ +static int APP_CC +construct_QUALITY_MODE(QUALITY_MODE *pdu) { + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + pdu->__destructor = &destroy_QUALITY_MODE; + + return 0; +} + +/*****************************************************************************/ +static int APP_CC +construct_SNDCLOSE(SNDCLOSE *pdu) { + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + pdu->__destructor = &destroy_SNDCLOSE; + pdu->Header.msgType = SNDC_CLOSE; + pdu->Header.bPad = 0x00; /* is this a magic number? although the MSDN docs indicate the value of this field is ignored, I used the value set forth in the MSDN example to be safe */ + pdu->Header.BodySize = 0; /* the total size in bytes for a basic PDU of this type is 16; however, the Header (which is 4 bytes in length) is not counted when calculating BodySize, so therefore the value of this field is initially set to 12 */ + + return 0; +} + +/*****************************************************************************/ +static int APP_CC +construct_SNDTRAINING(SNDTRAINING *pdu) { + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + pdu->__destructor = &destroy_SNDTRAINING; + pdu->Header.msgType = SNDC_TRAINING; + pdu->Header.bPad = 0x00; /* is this a magic number? although the MSDN docs indicate the value of this field is ignored, I used the value set forth in the MSDN example to be safe */ + pdu->Header.BodySize = 4; /* the total size in bytes for a basic PDU of this type is 16; however, the Header (which is 4 bytes in length) is not counted when calculating BodySize, so therefore the value of this field is initially set to 12 */ + + pdu->wTimeStamp = sound_get_local_time(); + pdu->wPackSize = 0x0000; + pdu->data = NULL; + + return 0; +} + +/*****************************************************************************/ +static int APP_CC +construct_SNDWAV(SNDWAV * pdu, unsigned int byteCount, BYTE * inData) { + int rv = 0; + uint32_t * pnum = (uint32_t *)NULL; + + if (pdu == NULL || byteCount < 1 || inData == NULL) { + rv = -1; + goto end; + } + + pnum = (uint32_t *)inData; + pdu->__destructor = &destroy_SNDWAV; + pdu->bPad = 0x00000000; + pdu->Data = inData; + + end:; + return rv; +} + +/*****************************************************************************/ +static int APP_CC +construct_SNDWAVINFO(SNDWAVINFO * pdu, unsigned int sndFormatIndex, size_t byteCount, BYTE * inData) { + int rv = 0; + int idx = 0; + unsigned int lmt = 0; + DWORD tmp = 0x00000000; + DWORD b[4] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; + SNDWAV * wav = (SNDWAV *)NULL; + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + if (pdu == NULL || (byteCount > 0 && inData == NULL)) { + rv = -1; + goto end; + } + + pdu->__destructor = &destroy_SNDWAVINFO; + if (byteCount > 3) { + b[0] = inData[0]; + b[1] = inData[1]; + b[2] = inData[2]; + b[3] = inData[3]; + + tmp = (b[0] & 0x000000ff) | ((b[1] & 0x000000ff) << 8) | ((b[2] & 0x000000ff) << 16) | ((b[3] & 0x000000ff) << 24); + } + else if (byteCount > 2) { + b[0] = inData[0]; + b[1] = inData[1]; + b[2] = inData[2]; + tmp = (b[0] & 0x000000ff) | ((b[1] & 0x000000ff) << 8) | ((b[2] & 0x000000ff) << 16); + } + else if (byteCount > 1) { + b[0] = inData[0]; + b[1] = inData[1]; + tmp = (b[0] & 0x000000ff) | ((b[1] & 0x000000ff) << 8); + } + else if (byteCount == 1) { + b[0] = inData[0]; + tmp = (b[0] & 0x000000ff); + } + + pdu->Header.msgType = SNDC_WAVE; + pdu->Header.bPad = 0x7e; /* is this a magic number? although the MSDN docs indicate the value of this field is ignored, I used the value set forth in the MSDN example to be safe */ + pdu->Header.BodySize = 8 + MAX(byteCount, 4); + pdu->wTimeStamp = sound_get_local_time(); + pdu->wFormatNo = sndFormatIndex; + pdu->bPad[0] = 0x00; + pdu->bPad[1] = 0x00; + pdu->bPad[2] = 0x00; + pdu->Data = tmp; + pdu->alen = (byteCount > 3) ? (byteCount - 4) : 0; + pdu->appendix = NULL; + + if (byteCount > 4) { + pdu->appendix = SOUND_NEW(SNDWAV); + construct_SNDWAV(pdu->appendix, (byteCount - 4), (inData + 4)); + } + + end:; + return rv; +} + + +/*****************************************************************************/ +static int APP_CC +sound_SNDCLOSE_out(struct stream* s, SNDCLOSE *pdu) { + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + /* Header [RDPSND PDU Header] */ + out_uint8(s, pdu->Header.msgType); + out_uint8(s, pdu->Header.bPad); + out_uint16_le(s, pdu->Header.BodySize); + + return 0; +} + +/*****************************************************************************/ +static int APP_CC +sound_SNDTRAINING_out(struct stream* s, SNDTRAINING *pdu) { + unsigned int idx = 0; + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + /* Header [RDPSND PDU Header] */ + out_uint8(s, pdu->Header.msgType); + out_uint8(s, pdu->Header.bPad); + out_uint16_le(s, pdu->Header.BodySize); + + out_uint16_le(s, pdu->wTimeStamp); + out_uint16_le(s, pdu->wPackSize); + + if ((pdu->data != NULL) && (pdu->wPackSize > 0)) { + out_uint8a(s, pdu->data, pdu->wPackSize); + } + + return 0; +} + +/*****************************************************************************/ +static int APP_CC +sound_SNDWAV_out(struct stream* s, SNDWAV *pdu, unsigned int byteCount) { + unsigned int idx = 0; + int lmt = 0; + int remain = 0; + int res = 0; + int tmp = 0; + char tbuf[256]; + + if (s==NULL || pdu == NULL || (byteCount > 0 && pdu->Data == NULL) || s->p == NULL || s->data == NULL || s->size < 1) { + MDBGLOG("sound","ERROR\t[%s()]: s = %p, pdu = %p, byteCount = %d",__func__,s,pdu,byteCount); + res = -1; + goto end; + } + + out_uint32_le(s, pdu->bPad); + + tmp = s->p - s->data; + remain = s->size - tmp; + lmt = byteCount; + if (byteCount > remain) { + lmt = remain; + } + if (lmt > 0) { + if (verbose) { + MDBGLOG("sound","DEBUG\t[%s()]: lmt = %d",__func__,lmt); + } + out_uint8a(s, pdu->Data, lmt); + res = lmt; + } + else { + MDBGLOG("sound","ERROR\t[%s()]: !!! ERROR (stream buffer overrun) !!!",__func__); + res = -1; + } + end:; + return res; +} + +/*****************************************************************************/ +static int APP_CC +sound_SNDWAVINFO_out(struct stream* s, SNDWAVINFO *pdu) { + + /* Header [RDPSND PDU Header] */ + out_uint8(s, pdu->Header.msgType); + out_uint8(s, pdu->Header.bPad); + out_uint16_le(s, pdu->Header.BodySize); + + out_uint16_le(s, pdu->wTimeStamp); + out_uint16_le(s, pdu->wFormatNo); + out_uint8(s, pdu->cBlockNo); + out_uint8(s, pdu->bPad[0]); + out_uint8(s, pdu->bPad[1]); + out_uint8(s, pdu->bPad[2]); + out_uint32_le(s, pdu->Data); + + return 0; +} + +/*****************************************************************************/ +static int APP_CC +construct_CLIENT_AUDIO_VERSION_AND_FORMATS(CLIENT_AUDIO_VERSION_AND_FORMATS * pdu) { + unsigned int idx = 0; + unsigned int lmt = 0; + AUDIO_FORMAT * tmp = (AUDIO_FORMAT *)NULL; + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + if (pdu == NULL) { + MDBGLOG("sound","ERROR\t[%s()]: pdu is NULL",__func__); + } + else { + pdu->__destructor = &destroy_CLIENT_AUDIO_VERSION_AND_FORMATS; + lmt = pdu->wNumberOfFormats; + for (idx=0;idxsndFormats[idx]; + construct_AUDIO_FORMAT(tmp); + } + } + return 0; } + +/*****************************************************************************/ +static int APP_CC +construct_SERVER_AUDIO_VERSION_AND_FORMATS(SERVER_AUDIO_VERSION_AND_FORMATS * pdu, char ** fmts, unsigned int fmtc) { + int rv = 0; + int idx = 0; + unsigned int lmt = 0; + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + if (pdu == NULL || (fmtc > 0 && fmts == NULL)) { + MDBGLOG("sound","ERROR\t[%s()]: pdu = %p, fmtc = %d, fmts = %p",__func__, pdu, fmtc, fmts); + rv = -1; + goto end; + } + + g_memset(&(pdu->lock),0,sizeof(tc_t)); + { + tc_t attr; + tc_p pattr = &attr; + TC_MUTATTR_INIT(pattr); + TC_MUTATTR_SETTYPE(pattr, TC_MUTEX_ERRORCHECK); + TC_MUTEX_INIT(&(pdu->lock), pattr); + } + TC_MUTEX_LOCK(&(pdu->lock)); + pdu->__destructor = &destroy_SERVER_AUDIO_VERSION_AND_FORMATS; + pdu->Header.msgType = SNDC_FORMATS; + pdu->Header.bPad = 0x2b; /* is this a magic number? although the MSDN docs indicate the value of this field is ignored, I used the value set forth in the MSDN example to be safe */ + pdu->Header.BodySize = 20; /* the total size in bytes for a basic PDU of this type is 24; however, the Header (which is 4 bytes in length) is not counted when calculating BodySize, so therefore the value of this field is initially set to 20 */ + pdu->dwFlags = 0x0000; + pdu->dwVolume = 0x0000; + pdu->dwPitch = 0x0000; + pdu->wDGramPort = 0x0000; + pdu->wNumberOfFormats = fmtc; + pdu->cLastBlockConfirmed = 0xff; + pdu->wVersion = 0x05; + pdu->bPad = 0x00; + lmt = pdu->wNumberOfFormats; + pdu->sndFormats = g_malloc(sizeof(size_t),lmt); + if (lmt>0) { + for (idx = 0; idx < lmt ; idx++) { + AUDIO_FORMAT * tmp = (AUDIO_FORMAT *)NULL; + sound_audioformat_from_name(&tmp, fmts[idx]); + pdu->sndFormats[idx] = tmp; + pdu->Header.BodySize = pdu->Header.BodySize + 18; + if (pdu->sndFormats[idx]->cbSize > 0) { + pdu->Header.BodySize = pdu->Header.BodySize + pdu->sndFormats[idx]->cbSize; + } + construct_AUDIO_FORMAT((AUDIO_FORMAT *)(pdu->sndFormats[idx])); + } + } + TC_MUTEX_UNLOCK(&(pdu->lock)); + + end:; + return rv; +} + +/*****************************************************************************/ +/* Server Audio Formats and Version PDU */ +static int APP_CC +sound_SERVER_AUDIO_VERSION_AND_FORMATS_out(struct stream* s, SERVER_AUDIO_VERSION_AND_FORMATS *pdu) { + + unsigned int idx, lmt; + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + /* Header [RDPSND PDU Header] */ + out_uint8(s, pdu->Header.msgType); /* msgType [1 byte uint] = SNDC_FORMATS = 0x01 */ + out_uint8(s, pdu->Header.bPad); /* bPad [1 byte uint] = 0 */ + out_uint16_le(s, pdu->Header.BodySize); /* BodySize [2 bytes uint] = 0 */ + + /* dwFlags [4 bytes uint] */ + out_uint32_le(s, pdu->dwFlags); + + /* dwVolume [4 bytes uint] */ + out_uint32_le(s, pdu->dwVolume); + + /* dwPitch [4 bytes uint] */ + out_uint32_le(s, pdu->dwPitch); + + /* wDGramPort [2 bytes uint] */ + out_uint16_le(s, pdu->wDGramPort); + + /* wNumberOfFormats [4 bytes uint] */ + out_uint16_le(s, pdu->wNumberOfFormats); + + /* cLastBlockConfirmed [1 byte uint] */ + out_uint8(s, pdu->cLastBlockConfirmed); + + /* wVersion [2 bytes uint] */ + out_uint16_le(s, pdu->wVersion); + + /* bPad [1 byte uint] */ + out_uint8(s, pdu->bPad); + + lmt = pdu->wNumberOfFormats; + for (idx = 0; idx < lmt ; idx++) { + sound_AUDIO_FORMAT_out(s, (AUDIO_FORMAT *)pdu->sndFormats[idx]); + } + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: done.",__func__); + } + + return 0; +} + + +/*****************************************************************************/ +/* UNIX signal to quit recieved */ +static void exit_signal_callback(pa_mainloop_api * m, pa_signal_event * e, int sig, void * userdata) { + if (verbose) { + MDBGLOG("sound", "INFO\t[%s()]: received exit signal", __func__); + } + pa_quit(0); +} + +/*****************************************************************************/ +int APP_CC +sound_init(void) { + struct stream * s = (struct stream *)NULL; + int size = 0; + int rv = 0; + int pid = 0; + SERVER_AUDIO_VERSION_AND_FORMATS tpdu; + SERVER_AUDIO_VERSION_AND_FORMATS * pdu = (SERVER_AUDIO_VERSION_AND_FORMATS *)(&tpdu); + WAVEFORMATEX afmt[7]; + char * sockname = (char *)NULL; + char * uname = (char *)NULL; + char * udir = (char *)NULL; + char * audio_fifo_path = (char *)NULL; + char wait_socket[512]; + char tbuf[512]; + int fd = 0; + int cv = 0; + int locked = 0; + tbus sck = 0; + struct timeval ltime; + double t = 0.; + + if (g_attr == NULL) { + g_attr = (tc_p)(&mutex_attribute); + TC_MUTATTR_INIT(g_attr); + TC_MUTATTR_SETTYPE(g_attr,TC_MUTEX_ERRORCHECK); + } + + TC_MUTEX_INIT(&g_cb_mutex, g_attr); + TC_MUTEX_INIT(&g_init_mutex, g_attr); + TC_MUTEX_INIT(&g_drain_mutex, g_attr); + TC_MUTEX_INIT(&g_event_mutex, g_attr); + TC_MUTEX_INIT(&g_underrun_mutex, g_attr); + TC_MUTEX_INIT(&g_stream_mutex, g_attr); + TC_MUTEX_INIT(&g_thread_mutex, g_attr); + TC_MUTEX_INIT(&g_ready_mutex, g_attr); + TC_MUTEX_INIT(&g_stream_ready_mutex, g_attr); + TC_MUTEX_INIT(&g_pause_mutex, g_attr); + TC_MUTEX_INIT(&g_pause_ack_mutex, g_attr); + TC_MUTEX_INIT(&g_new_mutex, g_attr); + TC_MUTEX_INIT(&g_buffer_mutex, g_attr); + TC_MUTEX_INIT(&g_sink_mutex, g_attr); + TC_MUTEX_INIT(&g_pa_mutex, g_attr); + TC_MUTEX_INIT(&g_sound_mutex, g_attr); + TC_MUTEX_INIT(&g_ins_mutex, g_attr); + TC_MUTEX_INIT(&g_pktq_mutex, g_attr); + TC_MUTEX_INIT(&g_audio_mutex, g_attr); + TC_MUTEX_INIT(&g_up_mutex, g_attr); + TC_MUTEX_INIT(&g_close_mutex, g_attr); + TC_MUTEX_INIT(&g_pktready_mutex, g_attr); + TC_MUTEX_INIT(&g_train_mutex, g_attr); + TC_MUTEX_INIT(&g_send_mutex, g_attr); + TC_MUTEX_INIT(&g_socket_mutex, g_attr); + TC_MUTEX_INIT(&g_prev_mutex, g_attr); + TC_MUTEX_INIT(&g_formats_mutex, g_attr); + TC_MUTEX_INIT(&g_block_mutex, g_attr); + + { + barr_formats = &g_formats_barr; + g_memset(barr_formats,0,sizeof(tc_t)); + TC_BARR_INIT(barr_formats, 2); + } + + if (mutex_sound == NULL) { + tc_t mattr; + tc_p pattr = &mattr; + mutex_sound = (tc_p)(&g_sound_mutex); + TC_MUTATTR_INIT(pattr); + TC_MUTATTR_SETTYPE(pattr,TC_MUTEX_ERRORCHECK); + TC_MUTEX_INIT(mutex_sound,pattr); + } + + if (mutex_sound != NULL) { + TC_MUTEX_LOCK(mutex_sound); + locked = 1; + } + + if (mutex_up == NULL) { + mutex_up = (tc_p)(&g_up_mutex); + TC_MUTEX_INIT(mutex_up,g_attr); + } + + TC_MUTEX_LOCK(mutex_up); + if (g_sound_up > 0) { + if (locked > 0 && mutex_sound != NULL) { + TC_MUTEX_UNLOCK(mutex_sound); + } + TC_MUTEX_UNLOCK(mutex_up); + return 0; + } + else { + TC_MUTEX_UNLOCK(mutex_up); + } + sound_deinit(); + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + rv = 0; + pid = g_getpid(); + + if (mutex_thread == NULL) { + tc_t mattr; + tc_p pattr = &mattr; + mutex_thread = (tc_p)(&g_thread_mutex); + TC_MUTATTR_INIT(pattr); + TC_MUTATTR_SETTYPE(pattr,TC_MUTEX_ERRORCHECK); + TC_MUTEX_INIT(mutex_thread,pattr); + } + + if (mutex_pa == NULL) { + tc_t mattr; + tc_p pattr = &mattr; + mutex_pa = (tc_p)(&g_pa_mutex); + TC_MUTATTR_INIT(pattr); + TC_MUTATTR_SETTYPE(pattr,TC_MUTEX_ERRORCHECK); + TC_MUTEX_INIT(mutex_pa,pattr); + } + + if (mutex_ins == NULL) { + tc_t mattr; + tc_p pattr = &mattr; + mutex_ins = (tc_p)(&g_ins_mutex); + TC_MUTATTR_INIT(pattr); + TC_MUTATTR_SETTYPE(pattr,TC_MUTEX_ERRORCHECK); + TC_MUTEX_INIT(mutex_ins,pattr); + } + + if (mutex_pktq == NULL) { + tc_t mattr; + tc_p pattr = &mattr; + mutex_pktq = (tc_p)(&g_pktq_mutex); + TC_MUTATTR_INIT(pattr); + TC_MUTATTR_SETTYPE(pattr,TC_MUTEX_ERRORCHECK); + TC_MUTEX_INIT(mutex_pktq,pattr); + } + + if (mutex_audio == NULL) { + tc_t mattr; + tc_p pattr = &mattr; + mutex_audio = (tc_p)(&g_audio_mutex); + TC_MUTATTR_INIT(pattr); + TC_MUTATTR_SETTYPE(pattr,TC_MUTEX_ERRORCHECK); + TC_MUTEX_INIT(mutex_audio,pattr); + } + + if (mutex_ready == NULL) { + tc_t mattr; + tc_p pattr = &mattr; + mutex_ready = (tc_p)(&g_ready_mutex); + TC_MUTATTR_INIT(pattr); + TC_MUTATTR_SETTYPE(pattr,TC_MUTEX_ERRORCHECK); + TC_MUTEX_INIT(mutex_ready,pattr); + } + + if (mutex_stream_ready == NULL) { + tc_t mattr; + tc_p pattr = &mattr; + mutex_stream_ready = (tc_p)(&g_stream_ready_mutex); + TC_MUTATTR_INIT(pattr); + TC_MUTATTR_SETTYPE(pattr,TC_MUTEX_ERRORCHECK); + TC_MUTEX_INIT(mutex_stream_ready,pattr); + } + + if (mutex_pause == NULL) { + tc_t mattr; + tc_p pattr = &mattr; + mutex_pause = (tc_p)(&g_pause_mutex); + mutex_pause_ack = (tc_p)(&g_pause_ack_mutex); + g_memset(pattr,0,sizeof(tc_t)); + TC_MUTATTR_INIT(pattr); + TC_MUTATTR_SETTYPE(pattr,TC_MUTEX_ERRORCHECK); + TC_MUTEX_INIT(mutex_pause,pattr); + TC_MUTEX_INIT(mutex_pause_ack,pattr); + g_memset(pattr,0,sizeof(tc_t)); + cond_pause = (tc_p)(&g_pause_cond); + cond_pause_ack = (tc_p)(&g_pause_ack_cond); + TC_CONDATTR_INIT(pattr); + TC_COND_CREATE(cond_pause,pattr); + TC_COND_CREATE(cond_pause_ack,pattr); + } + + if (mutex_new == NULL) { + tc_t mattr; + tc_p pattr = &mattr; + mutex_new = (tc_p)(&g_new_mutex); + TC_MUTATTR_INIT(pattr); + TC_MUTATTR_SETTYPE(pattr,TC_MUTEX_ERRORCHECK); + TC_MUTEX_INIT(mutex_new,pattr); + } + + if (mutex_buffer == NULL) { + tc_t mattr; + tc_p pattr = &mattr; + mutex_buffer = (tc_p)(&g_buffer_mutex); + TC_MUTATTR_INIT(pattr); + TC_MUTATTR_SETTYPE(pattr,TC_MUTEX_ERRORCHECK); + TC_MUTEX_INIT(mutex_buffer,pattr); + } + + if (mutex_out == NULL) { + tc_t mattr; + tc_p pattr = &mattr; + } + + TC_MUTEX_LOCK(mutex_ready); + g_ready_waiting = 0; + g_ready_count = 0; + TC_MUTEX_UNLOCK(mutex_ready); + + if (cond_pa == NULL) { + tc_t cattr; + tc_p pattr = (tc_p)(&cattr); + cond_pa = (tc_p)(&g_pa_cond); + TC_CONDATTR_INIT(pattr); + TC_COND_CREATE(cond_pa,pattr); + } + + if (cond_ready == NULL) { + tc_t cattr; + tc_p pattr = (tc_p)(&cattr); + cond_ready = (tc_p)(&g_ready_cond); + TC_CONDATTR_INIT(pattr); + TC_COND_CREATE(cond_ready,pattr); + } + + if (cond_stream_ready == NULL) { + tc_t cattr; + tc_p pattr = (tc_p)(&cattr); + cond_stream_ready = (tc_p)(&g_stream_ready_cond); + TC_CONDATTR_INIT(pattr); + TC_COND_CREATE(cond_stream_ready,pattr); + } + + if (mutex_close == NULL) { + mutex_close = (tc_p)(&g_close_mutex); + TC_MUTEX_INIT(mutex_close,g_attr); + } + + TC_MUTEX_LOCK(mutex_close); + g_received_close_pdu = 0; + TC_MUTEX_UNLOCK(mutex_close); + + if (mutex_pktq == NULL) { + mutex_pktq = (tc_p)(&g_pktq_mutex); + TC_MUTEX_INIT(mutex_pktq,g_attr); + } + + if (mutex_pktlog == NULL) { + mutex_pktlog = (tc_p)(&g_pktlog_mutex); + TC_MUTEX_INIT(mutex_pktlog,g_attr); + } + + if (mutex_pktready == NULL) { + mutex_pktready = (tc_p)(&g_pktready_mutex); + TC_MUTEX_INIT(mutex_pktready,g_attr); + } + + if (mutex_train == NULL) { + mutex_train = (tc_p)(&g_train_mutex); + TC_MUTEX_INIT(mutex_train,g_attr); + } + + if (mutex_send == NULL) { + mutex_send = (tc_p)(&g_send_mutex); + TC_MUTEX_INIT(mutex_send,g_attr); + } + + if (mutex_socket == NULL) { + mutex_socket = (tc_p)(&g_socket_mutex); + TC_MUTEX_INIT(mutex_socket,g_attr); + } + + if (mutex_prev == NULL) { + mutex_prev = (tc_p)(&g_prev_mutex); + TC_MUTEX_INIT(mutex_prev,g_attr); + } + + if (mutex_formats == NULL) { + mutex_formats = (tc_p)(&g_formats_mutex); + TC_MUTEX_INIT(mutex_formats,g_attr); + } + + if (mutex_block == NULL) { + mutex_block = (tc_p)(&g_block_mutex); + TC_MUTEX_INIT(mutex_block,g_attr); + } + + if (thread_pktq == NULL) { + thread_pktq = (tc_p)(&g_pktq_thread); + } + + if (thread_pa == NULL) { + thread_pa = (tc_p)(&g_pa_thread); + } + + g_memset(<ime,0,sizeof(struct timeval)); + g_memset(selfpipe_path,0,(512 * sizeof(char))); + TC_MUTEX_LOCK(mutex_pktlog); + g_memset(pktlog,0,(MAX_PKTLOG * sizeof(pktinfo))); + TC_MUTEX_UNLOCK(mutex_pktlog); + g_memset(afmt,0,(7 * sizeof(WAVEFORMATEX))); + TC_MUTEX_LOCK(mutex_socket); + g_memset(wait_socket,0,(512 * sizeof(char))); + TC_MUTEX_UNLOCK(mutex_socket); + g_memset(tbuf,0,(512 * sizeof(char))); + +#ifdef XRDP_ENABLE_SOXCONVERT + cv = g_soxconvert_init(); + if (verbose) { + MDBGLOG("sound","g_soxconvert_init: %d\0",cv); + } +#endif + + g_pktq = SOUND_NEW(pktq); + + audio_fifo_path = g_getenv("XRDP_AUDIO_FIFO"); + if ((audio_fifo_path != NULL) && (g_strlen(audio_fifo_path) > 0)) { + sockname = g_strndup(audio_fifo_path, 128); + } + if (verbose) { + MDBGLOG("sound"," ^^ sockname=%s; audio_fifo_path=%s",sockname,audio_fifo_path); + } + + #ifndef L_cuserid + #define L_cuserid 17 + #endif + uname = g_getenv("USER"); + if ((uname == NULL) || (g_strlen(uname) < 1)) { + if (pid > -1) { + g_snprintf(tbuf,255,CHANSRV_USERNAME_PATH,pid); + fd = g_file_open(tbuf); + if (fd > -1) { + uname = (char *)g_malloc((sizeof(char) * 256),1); + g_file_read(fd, uname, 255); + g_file_close(fd); + fd = 0; + } + } + } + if ((uname == NULL) || (g_strlen(uname) < 1)) { + MDBGLOG("sound","ERROR\t[%s()]: unable to ascertain username",__func__); + rv = -1; + if (locked > 0) { + TC_MUTEX_UNLOCK(mutex_sound); + } + return rv; + } + else if ((sockname == NULL) || (g_strlen(sockname) < 1)) { +#ifdef XRDP_ENABLE_PULSEAUDIO + udir = (char *)g_malloc(((g_strlen(uname) + g_strlen("/home//.pulse") + 1) * sizeof(char)),1); + g_snprintf(udir,((g_strlen(uname) + g_strlen("/home//.pulse") + 1) * sizeof(char)),"/home/%s/.pulse",uname); + sockname = get_audio_socket(udir); +#endif + } + if (verbose) { + MDBGLOG("sound"," ^^ (1) sockname=%s",sockname); + } + + TC_MUTEX_LOCK(mutex_audio); +#ifdef XRDP_ENABLE_ALSA + if ((g_audio == NULL) && ((audio_fifo_path == NULL) || (g_strlen(audio_fifo_path) < 1) || (g_file_exist(audio_fifo_path) < 1)) && ((sockname == NULL) || (g_strlen(sockname) < 1) || (g_file_exist(sockname) < 1))) { + sockname = g_strdup("/tmp/fifo-alsa-output"); + cv = g_alsa_init(); + if ((cv > -1) && (g_alsa != NULL)) { + g_alsa->setup_fifo(g_alsa,sockname); + } + MDBGLOG("sound"," ^^ g_alsa_init: %d\0",cv); + } + MDBGLOG("sound"," ^^ (2) sockname=%s\0",sockname); +#endif + + g_memset(tbuf,0,sizeof(char) * 512); + g_snprintf(selfpipe_path,511,SELFPIPE_PATH,pid); + if (g_audio != NULL) { + MDBGLOG("sound","DEBUG\t[%s()]: calling trans_delete()",__func__); + trans_delete(g_audio); + } + if (g_audio_socket_type == WO_LOCAL) { + g_audio = trans_create(g_audio_socket_type, MAX_STREAM, MAX_STREAM); + g_audio->header_size = 0; + g_audio->callback_data = g_audio; + g_audio->ready = 1; + g_audio->rtime = 0.; + g_sound_wait_obj = g_create_wait_obj_from_socket(g_audio->sck, 1); + } + else if (g_audio_socket_type == WO_FIFO) { + g_audio = trans_create(g_audio_socket_type, MAX_STREAM, MAX_STREAM); + g_audio->header_size = 0; + g_audio->callback_data = g_audio; + g_audio->ready = 1; + g_audio->rtime = 0.; + g_sound_wait_obj = g_create_wait_obj_from_fifo(g_audio->sck,0); + } + TC_MUTEX_UNLOCK(mutex_audio); + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: fd = %d; g_sound_wait_obj = %d",__func__,fd,g_sound_wait_obj); + } + + if (rv == 0) { + char * sndFormatArray[] = {"alaw", "msg723", "mp3", "mulaw", "ima_adpcm", "adpcm", "hipcm", "gsm610" }; + + if (pdu == NULL) { + MDBGLOG("sound","ERROR\t[%s()]: pdu is NULL",__func__); + rv = 4; + } + else { + construct_SERVER_AUDIO_VERSION_AND_FORMATS(pdu, sndFormatArray, 8); + TC_MUTEX_LOCK(mutex_formats); + server_formats = pdu; + TC_MUTEX_UNLOCK(mutex_formats); + + make_stream(s); + if (s == NULL) { + MDBGLOG("sound","ERROR\t[%s()]: make_stream() failed",__func__); + rv = 4; + } + else { + tc_t * lt = (tc_t *)NULL; + tc_t tattr; + tc_p pattr = (tc_p)(&tattr); + g_memset(pattr,0,sizeof(tc_t)); + lt = (tc_t *)g_malloc(sizeof(tc_t), 1); + TC_THREADATTR_INIT(pattr); + TC_THREADATTR_SETDETACHSTATE(pattr, TC_CREATE_JOINABLE); + init_stream(s, MAX_STREAM); + sound_SERVER_AUDIO_VERSION_AND_FORMATS_out(s, pdu); + s_mark_end(s); + size = (int)(s->end - s->data); + TC_MUTEX_LOCK(mutex_out); + rv = send_channel_data(g_rdpsnd_chan_id, s->data, size); + TC_MUTEX_UNLOCK(mutex_out); + TC_MUTEX_LOCK(mutex_thread); + TC_THREAD_INIT_FULL(&(lt->thread), (const tc_threadattr_t *)pattr, &sound_timer_loop, NULL); + TC_MUTEX_UNLOCK(mutex_thread); + if (rv != 0) + { + MDBGLOG("sound","ERROR\t[%s()]: send_channel_data() failed (rv = %d)",__func__,rv); + rv = 4; + } + free_stream(s); + } + } + //g_free(sndFormatArray[6]); + //g_free(sndFormatArray[5]); + //g_free(sndFormatArray[4]); + //g_free(sndFormatArray[3]); + //g_free(sndFormatArray[2]); + //g_free(sndFormatArray[1]); + //g_free(sndFormatArray[0]); + //g_free(sndFormatArray); + } + + /* spawn pktq thread: */ + if (mutex_thread != NULL) { + tc_t tattr; + tc_p pattr = (tc_p)(&tattr); + g_memset(pattr,0,sizeof(tc_t)); + TC_MUTEX_LOCK(mutex_thread); + TC_THREADATTR_INIT(pattr); + TC_THREADATTR_SETDETACHSTATE(pattr, TC_CREATE_JOINABLE); + TC_THREAD_INIT_FULL(&(thread_pktq->thread), (const tc_threadattr_t *)pattr, &sound_pktq_loop, NULL); + TC_MUTEX_UNLOCK(mutex_thread); + } + + /* spawn pulseaudio thread: */ + if (mutex_pa != NULL) { + int tlocked = 0; + tc_t tattr; + tc_p pattr = (tc_p)(&tattr); + g_memset(pattr,0,sizeof(tc_t)); + TC_MUTEX_LOCK(mutex_pa); + TC_THREADATTR_INIT(pattr); + TC_THREADATTR_SETDETACHSTATE(pattr, TC_CREATE_JOINABLE); + TC_THREAD_INIT_FULL(&(thread_pa->thread), (const tc_threadattr_t *)pattr, &sound_pa_start, NULL); + TC_MUTEX_UNLOCK(mutex_pa); + } + + if (rv == 0) { + if (0 && g_sound_up < 1) { + TC_MUTEX_LOCK(mutex_up); + if (g_sound_up < 1) { + g_sound_up = 1; + } + TC_MUTEX_UNLOCK(mutex_up); + } + } + else { + MDBGLOG("sound","ERROR\t[%s()]: error on exit (rv = %d)",__func__,rv); + } + + if (locked > 0) { + TC_MUTEX_UNLOCK(mutex_sound); + } + return rv; +} + +static void * APP_CC sound_pa_start(void * inarg) { + int ret = 0; + int done = 0; + int idx = 0; + unsigned int qcnt; + const char * server = (const char *)NULL; + const char client_name[] = "xrdpsnd"; + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + if (g_received_close_pdu > 0) { + goto exit; + } + + if (!g_pa_ready) { + TC_MUTEX_LOCK(mutex_pa); + if (!g_pa_ready) { + TC_COND_WAIT(cond_pa,mutex_pa); + } + TC_MUTEX_UNLOCK(mutex_pa); + } + + /* Set up a new main loop */ + if (XRDP_THREADED_PA_MAINLOOP) { + if (!(mt = pa_threaded_mainloop_new())) { + MDBGLOG("sound", "ERROR\t[%s()]: pa_threaded_mainloop_new() failed.", __func__); + TC_MUTEX_UNLOCK(mutex_pa); + goto quit; + } + mainloop_api = pa_threaded_mainloop_get_api(mt); + } + else { + if (!(m = pa_mainloop_new())) { + MDBGLOG("sound", "ERROR\t[%s()]: pa_mainloop_new() failed.", __func__); + TC_MUTEX_UNLOCK(mutex_pa); + goto quit; + } + mainloop_api = pa_mainloop_get_api(m); + } + + if (mainloop_api == NULL) { + MDBGLOG("sound", "ERROR\t[%s()]: pa_mainloop_get_api() failed.", __func__); + TC_MUTEX_UNLOCK(mutex_pa); + goto quit; + } + + //pa_signal_new(SIGINT, pa_exit_signal_callback, NULL); + //pa_signal_new(SIGTERM, pa_exit_signal_callback, NULL); + //pa_disable_sigpipe(); + + TC_MUTEX_LOCK(mutex_event); + if (!(stdio_event = mainloop_api->io_new(mainloop_api, + mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO, + mode == PLAYBACK ? PA_IO_EVENT_INPUT : PA_IO_EVENT_OUTPUT, + mode == PLAYBACK ? stdin_callback : stdout_callback, NULL))) { + TC_MUTEX_UNLOCK(mutex_event); + MDBGLOG("sound","ERROR\t[%s()]: io_new() failed",__func__); + goto quit; + } + TC_MUTEX_UNLOCK(mutex_event); + + if (0 && sound_get_pulseaudio_server(&server) < 0) { + MDBGLOG("sound","ERROR\t[%s()]: failed to ascertain PulseAudio server",__func__); + goto quit; + } + else do { + int tres = 0; + unsigned char tc = 0; + /* Create a new connection context */ + if (!(context = pa_context_new(mainloop_api, client_name))) { + MDBGLOG("sound", "ERROR\t[%s()]: pa_context_new() failed.", __func__); + TC_MUTEX_UNLOCK(mutex_pa); + goto quit; + } + pa_context_set_state_callback(context, &context_state_callback, NULL); + pa_context_set_subscribe_callback(context, &pa_subscribe_cb, NULL); + TC_MUTEX_LOCK(mutex_init); + if (context != NULL && pa_context_get_state(context) != PA_CONTEXT_READY) { tres = pa_context_connect(context, server, PA_CONTEXT_NOFAIL, NULL); } + if (tres < 0) { + TC_MUTEX_UNLOCK(mutex_init); + MDBGLOG("sound", "ERROR\t[%s()]: pa_context_connect() failed: %s, trying again", __func__, pa_strerror(pa_context_errno(context))); + pa_xfree(context); + context = (pa_context *)NULL; + g_sleep(1000); + } + else { + TC_COND_WAIT(cond_init, mutex_init); + TC_MUTEX_UNLOCK(mutex_init); + break; + } + TC_MUTEX_UNLOCK(mutex_init); + } while (!(context != NULL && pa_context_get_state(context) == PA_CONTEXT_READY)); + + TC_MUTEX_UNLOCK(mutex_pa); + + /* Start the PulseAudio mainloop thread */ + if (XRDP_THREADED_PA_MAINLOOP) { + pa_threaded_mainloop_start(mt); + goto exit; + } + + quit:; + { + TC_MUTEX_LOCK(mutex_pa); + if (stream) { + pa_stream_unref(stream); + } + if (context) { + pa_context_unref(context); + } + TC_MUTEX_LOCK(mutex_event); + if (stdio_event) { + assert(mainloop_api); + mainloop_api->io_free(stdio_event); + } + TC_MUTEX_UNLOCK(mutex_event); + if (mt) { + pa_signal_done(); + pa_threaded_mainloop_free(mt); + } + else if (m) { + pa_signal_done(); + pa_mainloop_free(m); + } + pa_xfree(buffer); + pa_xfree(device); + TC_MUTEX_UNLOCK(mutex_pa); + } + + exit:; + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: done.",__func__); + } + TC_THREAD_EXIT(NULL); +} + + +/*****************************************************************************/ +static char * APP_CC +get_audio_socket(const char * dirname) { + char * sub = (char *)NULL; + char * tmp = (char *)NULL; + char * ret = (char *)NULL; + char ** dirlist = (char **)NULL; + int dirlist_count = 0; + int idx = 0; + dirlist = g_dir_list_contents(dirname, dirlist, &dirlist_count); + while (idx < dirlist_count && tmp==NULL) { + sub = dirlist[idx]; + tmp = g_strstr(sub,"runtime"); + idx++; + } + tmp = sub; + idx = g_strlen(dirname) + g_strlen("/") + g_strlen(tmp) + g_strlen("/fifo_output") + 4; + ret = (char *)g_malloc((sizeof(char) * idx),1); + g_snprintf(ret,idx,"%s/%s/%s\0",dirname,tmp,"fifo_output"); + return ret; +} + + +/*****************************************************************************/ +static int APP_CC +closeAudio() { + int rv = 0; + int size = 0; + SNDCLOSE * pdu = (SNDCLOSE *)NULL; + LOCAL_STREAM(s); + + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + + pdu = SOUND_NEW(SNDCLOSE); + sound_SNDCLOSE_out(s, pdu); + s_mark_end(s); + size = (int)(s->end - s->data); + TC_MUTEX_LOCK(mutex_out); + rv = send_channel_data(g_rdpsnd_chan_id, s->data, size); + TC_MUTEX_UNLOCK(mutex_out); + SOUND_FREE(pdu); + + return 0; +} + +/*****************************************************************************/ +int APP_CC sound_deinit() { + int cv = 0; + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + //cv = g_alsa_deinit(); + //MDBGLOG("sound","g_alsa_deinit: %d",cv); + //unlink(ALSAFIFO_PATH); + + g_received_close_pdu = 1; + + g_sleep(150); + + if (g_sound_up && cond_ready != NULL) { + TC_MUTEX_LOCK(mutex_ready); + if (g_ready_waiting > 0) { + if (g_ready_waiting > 0) { + TC_COND_BROADCAST(cond_ready); + } + else { + TC_COND_SIGNAL(cond_ready); + } + g_sleep(150); + } + TC_MUTEX_UNLOCK(mutex_ready); + g_sleep(150); + //pa_quit(0); + } + + if (mutex_thread != NULL) { + TC_MUTEX_LOCK(mutex_thread); + if (thread_pktq != NULL) { + TC_THREAD_KILL(thread_pktq->thread); + g_sleep(100); + //TC_THREAD_JOIN(thread_pktq->thread, NULL); + thread_pktq = (tc_p)NULL; + } + if (thread_pa != NULL) { + TC_THREAD_KILL(thread_pa->thread); + g_sleep(100); + //TC_THREAD_JOIN(thread_pa->thread, NULL); + thread_pa = (tc_p)NULL; + } + TC_MUTEX_UNLOCK(mutex_thread); + TC_MUTEX_DEINIT(mutex_thread); + mutex_thread = (tc_p)NULL; + } + + if (mutex_pa != NULL) { + TC_MUTEX_LOCK(mutex_pa); + if (thread_pa != NULL) { + TC_THREAD_JOIN(thread_pa->thread, NULL); + thread_pa = (tc_p)NULL; + } + TC_MUTEX_UNLOCK(mutex_pa); + TC_MUTEX_DEINIT(mutex_pa); + mutex_pa = (tc_p)NULL; + } + + TC_MUTEX_LOCK(mutex_up); + if (g_sound_up > 0) { + TC_MUTEX_UNLOCK(mutex_up); + TC_MUTEX_LOCK(mutex_close); + if (g_received_close_pdu == 0) { closeAudio(); } + TC_MUTEX_UNLOCK(mutex_close); + TC_MUTEX_LOCK(mutex_formats); + TC_MUTEX_UNLOCK(mutex_formats); + } + else { + TC_MUTEX_UNLOCK(mutex_up); + } + + TC_MUTEX_LOCK(mutex_socket); + if (g_sound_wait_obj > -1) { + g_delete_wait_obj(g_sound_wait_obj); + g_sound_wait_obj = -1; + } + if (g_sound_selfpipe > -1) { + g_delete_wait_obj(g_sound_selfpipe); + unlink(selfpipe_path); + g_sound_selfpipe = -1; + } + TC_MUTEX_UNLOCK(mutex_socket); + + TC_MUTEX_LOCK(mutex_up); + if (g_sound_up > 0) { + TC_MUTEX_UNLOCK(mutex_up); + TC_MUTEX_LOCK(mutex_socket); + if (g_sound_socket > -1) { + g_file_close(g_sound_socket); + } + g_sound_socket = -1; + TC_MUTEX_UNLOCK(mutex_socket); + TC_MUTEX_LOCK(mutex_ins); + if (g_ins != NULL) { free_stream(g_ins); } + g_ins = NULL; + TC_MUTEX_UNLOCK(mutex_ins); + TC_MUTEX_LOCK(mutex_pktq); + if (g_pktq != NULL) { SOUND_FREE(g_pktq); } + g_pktq = NULL; + TC_MUTEX_UNLOCK(mutex_pktq); + TC_MUTEX_LOCK(mutex_up); + g_sound_up = 0; + TC_MUTEX_UNLOCK(mutex_up); + } + else { + TC_MUTEX_UNLOCK(mutex_up); + } + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: done.",__func__); + } + return 0; +} + +/*****************************************************************************/ +static int APP_CC +trainAudio() { + int rv = 0; + int size = 0; + SNDTRAINING *pdu = (SNDTRAINING *)NULL; + LOCAL_STREAM(s); + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + //TC_MUTEX_LOCK(mutex_new); + pdu = SOUND_NEW(SNDTRAINING); + //TC_MUTEX_UNLOCK(mutex_new); + + sound_SNDTRAINING_out(s, pdu); + s_mark_end(s); + size = (int)(s->end - s->data); + + TC_MUTEX_LOCK(mutex_sound); + TC_MUTEX_LOCK(mutex_out); + rv = send_channel_data(g_rdpsnd_chan_id, s->data, size); + TC_MUTEX_UNLOCK(mutex_out); + TC_MUTEX_UNLOCK(mutex_sound); + + SOUND_FREE(pdu); + + return 0; +} + +/*****************************************************************************/ +static unsigned int APP_CC +flength(FILE *fp) { + BYTE *buf = NULL; + unsigned int res = 0; + + if (fp != NULL) { + fseek(fp, 0, SEEK_END); + res = ftell(fp); + rewind(fp); + } + + return res; +} + + +/*****************************************************************************/ +int APP_CC +sound_data_in(struct stream * s, int chan_id, int chan_flags, int length, int total_length) { + int rv = 0; + int size = 0; + int lidx = -1; + int ins_locked = 0; + struct stream * ls = (struct stream *)NULL; + SNDPROLOG hdr; + void * inPDU = (void *)NULL; + unsigned int idx = 0; + unsigned int lmt = 0; + CLIENT_AUDIO_VERSION_AND_FORMATS tmp; + AUDIO_FORMAT * ltmp = (AUDIO_FORMAT *)NULL; + AUDIO_FORMAT * afmt = (AUDIO_FORMAT *)NULL; + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + } + + g_memset(&hdr,0,sizeof(SNDPROLOG)); + g_memset(&tmp,0,sizeof(CLIENT_AUDIO_VERSION_AND_FORMATS)); + + if ((chan_flags & 3) == 3) { + ls = s; + } + else { + TC_MUTEX_LOCK(mutex_ins); + ins_locked = 1; + if (chan_flags & 1) { + } + if ((chan_flags & 2) == 0) { + TC_MUTEX_UNLOCK(mutex_ins); + ins_locked = 0; + return 0; + } + g_ins = s; + ls = g_ins; + } + + rv = 0; + sound_SNDPROLOG_in(ls, &hdr); + switch (hdr.msgType) { + case 0x01: /* SNDC_CLOSE: Close PDU */ + rv = sound_process_SNDC_CLOSE(ls, &hdr); + break; + case 0x02: /* SNDC_WAVE: WaveInfo PDU */ + break; + case 0x03: /* SNDC_SETVOLUME: Volume PDU */ + break; + case 0x04: /* SNDC_SETPITCH: Pitch PDU */ + break; + case 0x05: /* SNDC_WAVECONFIRM: Wave Confirm PDU */ + inPDU = SOUND_NEW(SNDWAV_CONFIRM); + rv = sound_process_SNDC_WAVECONFIRM(ls, &hdr, (SNDWAV_CONFIRM *)inPDU); + TC_MUTEX_LOCK(mutex_drain); + if (cond_drain != NULL && g_drain > 0 && (g_outstanding < 1 || g_outstanding_playtime < g_target_latency)) { + TC_COND_SIGNAL(cond_drain); + } + TC_MUTEX_UNLOCK(mutex_drain); + if (inPDU != NULL && !g_callee_frees) { + if (((SNDWAV_CONFIRM *)inPDU)->__destructor != NULL) { + ((SNDWAV_CONFIRM *)inPDU)->__destructor(inPDU); + } + else { + g_free(inPDU); + } + inPDU = NULL; + } + break; + case 0x06: /* SNDC_TRAINING: Training PDU or Training Confirm PDU */ + inPDU = SOUND_NEW(SNDTRAININGCONFIRM); + rv = sound_process_SNDC_TRAININGCONFIRM(ls, &hdr, (SNDTRAININGCONFIRM *)inPDU); + if (rv == 0) { + TC_MUTEX_LOCK(mutex_send); + g_sound_ready_to_send = 1; + TC_MUTEX_UNLOCK(mutex_send); + } + if (inPDU != NULL && !g_callee_frees) { + if (inPDU != NULL && ((SNDTRAININGCONFIRM *)inPDU)->__destructor != NULL) { + ((SNDTRAININGCONFIRM *)inPDU)->__destructor(inPDU); + } + else { + g_free(inPDU); + } + inPDU = NULL; + } + break; + case 0x07: /* SNDC_FORMATS: Server Audio Formats and Version PDU or Client Audio Formats and Version PDU */ + inPDU = SOUND_NEW(CLIENT_AUDIO_VERSION_AND_FORMATS); + TC_MUTEX_LOCK(mutex_formats); + g_client_formats_received = 1; + client_formats = (CLIENT_AUDIO_VERSION_AND_FORMATS *)inPDU; + rv = sound_process_SNDC_FORMATS(ls, &hdr, client_formats); + construct_CLIENT_AUDIO_VERSION_AND_FORMATS(client_formats); + lmt = client_formats->wNumberOfFormats; + g_client_format_count += lmt; + TC_MUTEX_UNLOCK(mutex_formats); + for (idx=0;idx>>> [Format #%d]",(idx + 1)); + MDBGLOG("sound"," >>>> * wFormatTag: 0x%8.8x\0",((CLIENT_AUDIO_VERSION_AND_FORMATS *)inPDU)->sndFormats[idx]->wFormatTag); + MDBGLOG("sound"," >>>> * nChannels: %d\0",((CLIENT_AUDIO_VERSION_AND_FORMATS *)inPDU)->sndFormats[idx]->nChannels); + MDBGLOG("sound"," >>>> * nBlockAlign: %d\0",((CLIENT_AUDIO_VERSION_AND_FORMATS *)inPDU)->sndFormats[idx]->nBlockAlign); + MDBGLOG("sound"," >>>> * nSamplesPerSec: %d\0",((CLIENT_AUDIO_VERSION_AND_FORMATS *)inPDU)->sndFormats[idx]->nSamplesPerSec); + MDBGLOG("sound"," >>>> * nAvgBytesPerSec: %d\0",((CLIENT_AUDIO_VERSION_AND_FORMATS *)inPDU)->sndFormats[idx]->nAvgBytesPerSec); + MDBGLOG("sound"," >>>> * wBitsPerSample: %d\0",((CLIENT_AUDIO_VERSION_AND_FORMATS *)inPDU)->sndFormats[idx]->wBitsPerSample); + MDBGLOG("sound"," >>>> * cbSize: %d\n",((CLIENT_AUDIO_VERSION_AND_FORMATS *)inPDU)->sndFormats[idx]->cbSize); + if (((CLIENT_AUDIO_VERSION_AND_FORMATS *)inPDU)->sndFormats[idx]->wFormatTag == g_preferred_wave_format) { + if (verbose) { + MDBGLOG("sound","DEBUG\t[%s()]: found (idx = %d, wFormatTag = 0x%8.8x)",__func__,idx,((CLIENT_AUDIO_VERSION_AND_FORMATS *)inPDU)->sndFormats[idx]->wFormatTag); + } + ltmp = ((CLIENT_AUDIO_VERSION_AND_FORMATS *)inPDU)->sndFormats[idx]; + lidx = idx; + } + } + if ((lidx > -1) && (ltmp != NULL) && (client_formats != NULL) && (client_formats->sndFormats != NULL) && (client_formats->sndFormats[lidx] != NULL)) { + TC_MUTEX_LOCK(mutex_formats); + g_client_format_index = lidx; + g_client_format = client_formats->sndFormats[g_client_format_index]->wFormatTag; + g_format_byte_rate = ltmp->nAvgBytesPerSec; + TC_MUTEX_UNLOCK(mutex_formats); + MDBGLOG("sound","DEBUG\t[%s()]: found [final] (lidx = %d, wFormatTag = 0x%8.8x)",__func__,lidx,((CLIENT_AUDIO_VERSION_AND_FORMATS *)inPDU)->sndFormats[lidx]->wFormatTag); + } + TC_MUTEX_LOCK(mutex_train); + g_sound_ready_to_train = 1; + TC_MUTEX_UNLOCK(mutex_train); + TC_BARR_WAIT(barr_formats); + break; + case 0x08: /* SNDC_CRYPTKEY: Crypt Key PDU */ + break; + case 0x09: /* SNDC_WAVEENCRYPT: Wave Encrypt PDU */ + break; + case 0x0A: /* SNDC_UDPWAVE: UDP Wave PDU */ + break; + case 0x0B: /* SNDC_UDPWAVELAST: UDP Wave Last PDU */ + break; + case 0x0C: /* SNDC_QUALITYMODE: Quality Mode PDU */ + inPDU = SOUND_NEW(QUALITY_MODE); + rv = sound_process_SNDC_QUALITYMODE(ls, &hdr, (QUALITY_MODE *)inPDU); + break; + default: + MDBGLOG("sound", "WARNING\t[%s()]: unknown hdr.msgType (%d)", __func__, hdr.msgType); + break; + } + + if (ins_locked > 0) { + TC_MUTEX_UNLOCK(mutex_ins); + } + + return rv; +} + +/*****************************************************************************/ +int APP_CC +sound_get_wait_objs(tbus * objs, int * count, int * timeout) +{ + int lcount = 0; + int res = 0; + if (g_received_close_pdu > 0) { + goto exit; + } + TC_MUTEX_LOCK(mutex_up); + TC_MUTEX_LOCK(mutex_pktq); + if ((g_sound_up == 0) || (objs == 0) || (count == 0) || (g_pktq == NULL)) + { + TC_MUTEX_UNLOCK(mutex_pktq); + TC_MUTEX_UNLOCK(mutex_up); + res = 0; + } + else { + TC_MUTEX_UNLOCK(mutex_pktq); + TC_MUTEX_UNLOCK(mutex_up); + lcount = (*count); + TC_MUTEX_LOCK(mutex_socket); + if (g_sound_wait_obj > -1) { + TC_MUTEX_LOCK(mutex_send); + TC_MUTEX_LOCK(mutex_pktq); + if (g_sound_ready_to_send > 0 && g_pktq != NULL && g_pktq->getCount != NULL && g_pktq->getCount(g_pktq) > 0 && g_sound_wait_obj > -1) { + objs[lcount] = g_sound_wait_obj; + lcount++; + } + TC_MUTEX_UNLOCK(mutex_pktq); + TC_MUTEX_UNLOCK(mutex_send); + } + TC_MUTEX_UNLOCK(mutex_socket); + *count += lcount; + res = 0; + } + exit:; + return res; +} + +/*****************************************************************************/ +int APP_CC +sound_check_wait_objs(void) { + int rv = 0; + if (g_received_close_pdu > 0) { + goto exit; + } + TC_MUTEX_LOCK(mutex_up); + if (!g_sound_up || g_pktq == NULL) { + TC_MUTEX_UNLOCK(mutex_up); + rv = 0; + } + else { + TC_MUTEX_UNLOCK(mutex_up); + TC_MUTEX_LOCK(mutex_send); + if (g_sound_ready_to_send > 0) { + TC_MUTEX_UNLOCK(mutex_send); + TC_MUTEX_LOCK(mutex_socket); + if (g_sound_wait_obj > -1 && g_is_wait_obj_set(g_sound_wait_obj)) { + TC_MUTEX_UNLOCK(mutex_socket); + TC_MUTEX_LOCK(mutex_audio); + trans_check_wait_objs(g_audio); + TC_MUTEX_UNLOCK(mutex_audio); + } + else { + TC_MUTEX_UNLOCK(mutex_socket); + } + } + else { + TC_MUTEX_UNLOCK(mutex_send); + } + rv = 0; + } + exit:; + return rv; +} + +/*****************************************************************************/ +static void * APP_CC +sound_pktq_loop(void * inarg) { + int rv = 0; + int tmp = 0; + int qcnt = 0; + int done = 0; + int empty = 0; + int idle_count = 0; + size_t size = 0; + struct stream * ls = (struct stream *)NULL; + struct stream * ms = (struct stream *)NULL; + pkt * packet = (pkt *)NULL; + struct timeval time; + double t = 0.; + double dt = 0.; + double dtmp = 0.; + unsigned char plock = 0; + const unsigned int max_idle = 20; + long int ttime = 0; + long int tdiff = 0; + BYTE buf[1] = { 0 }; + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called [%d, %d]",__func__,g_getpid(),g_gettid()); + } + + if (g_received_close_pdu > 0) { + goto exit; + } + + TC_MUTEX_LOCK(mutex_pa); + TC_COND_WAIT(cond_pa,mutex_pa); + TC_MUTEX_UNLOCK(mutex_pa); + + g_memset(&time,0,sizeof(struct timeval)); + done = 0; + + TC_MUTEX_LOCK(mutex_close); + done = g_received_close_pdu; + TC_MUTEX_UNLOCK(mutex_close); + + while (!done) { + MB; + if (!g_thunk && (g_stream_ready < 1 || g_sound_up < 1 || (g_sound_up > 0 && g_stream_ready > 0 && g_outstanding_playtime > g_max_latency))) { + unsigned char proceed = 0; + if (mutex_stream_ready != NULL && cond_stream_ready != NULL) { + TC_MUTEX_LOCK(mutex_stream_ready); + if (g_stream_ready < 1) { + TC_COND_WAIT(cond_stream_ready, mutex_stream_ready); + proceed = 1; + TC_MUTEX_UNLOCK(mutex_stream_ready); + if (1 || verbose) { + MDBGLOG("sound","DEBUG\t[%s()]: woken up",__func__); + } + } + else if (g_enable_skew_compensation > 0) { + if (g_outstanding_playtime > g_max_latency) { + TC_MUTEX_UNLOCK(mutex_stream_ready); + g_sleep(180); + } + } + } + if (g_enable_skew_compensation > 0 && g_stream_ready > 0 && g_sound_up > 0 && g_outstanding_playtime > g_max_latency) { + TC_MUTEX_LOCK(mutex_drain); + if (g_stream_ready > 0 && g_sound_up > 0 && (g_outstanding_playtime > g_max_latency)) { + tc_t pattr; + tc_t * attr = &pattr; + TC_CONDATTR_INIT(attr); + TC_COND_CREATE(cond_drain, attr); + if (1 || verbose) { + MDBGLOG("sound","DEBUG\t[%s()]: waiting to drain...",__func__); + } + ttime = g_time2(); + g_drain = 1; + TC_COND_TIMEDWAIT(cond_drain, mutex_drain, g_max_latency); + tdiff = g_time2() - ttime; + g_drain = 0; + if (1 || verbose) { + MDBGLOG("sound","DEBUG\t[%s()]: drained. (tdiff = %d)",__func__,tdiff); + } + } + TC_MUTEX_UNLOCK(mutex_drain); + proceed = 0; + } + else if (g_enable_skew_compensation > 0 && g_stream_ready > 0 && g_sound_up > 0 && g_outstanding_playtime > g_high_latency) { + g_sleep(g_target_latency); + } + else if (g_enable_skew_compensation > 0 && g_stream_ready > 0 && g_sound_up > 0 && g_outstanding_playtime > g_target_latency) { + g_sleep(g_target_latency / 2); + //proceed = 1; + } + if (!proceed) { + TC_MUTEX_LOCK(mutex_close); + done = g_received_close_pdu; + TC_MUTEX_UNLOCK(mutex_close); + continue; + } + } + if (idle_count > max_idle && g_sound_up > 0 && g_sound_ready_to_send > 0 && g_ready_count < 1) { + tc_t cattr; + tc_p pattr = (tc_p)(&cattr); + g_memset(pattr,0,sizeof(tc_t)); + TC_CONDATTR_INIT(pattr); + TC_MUTEX_LOCK(mutex_ready); + if (g_ready_count > 0) { + TC_MUTEX_UNLOCK(mutex_ready); + TC_MUTEX_LOCK(mutex_close); + done = g_received_close_pdu; + TC_MUTEX_UNLOCK(mutex_close); + continue; + } + cond_ready = &g_ready_cond; + g_ready_triggered = 0; + TC_COND_CREATE(cond_ready, pattr); + if (g_ready_count < 1) { + TC_MUTEX_UNLOCK(mutex_ready); + TC_MUTEX_LOCK(mutex_ready); + } + if (g_ready_count < 1) { + g_ready_waiting++; + g_idle = 1; + if (1 || verbose) { + MDBGLOG("sound","DEBUG\t[%s()]: waiting...",__func__); + } + ttime = g_time2(); + TC_COND_WAIT(cond_ready, mutex_ready); + tdiff = g_time2() - ttime; + if (1 || verbose) { + MDBGLOG("sound","DEBUG\t[%s()]: finished (tdiff = %d)",__func__,tdiff); + } + g_ready_waiting--; + } + g_idle = 0; + if (g_ready_count < 1) { + TC_MUTEX_UNLOCK(mutex_ready); + TC_MUTEX_LOCK(mutex_close); + done = g_received_close_pdu; + TC_MUTEX_UNLOCK(mutex_close); + continue; + } + else if (!g_ready_triggered) { + TC_MUTEX_LOCK(mutex_pktq); + if (g_pktq != NULL && g_pktq->deq != NULL && g_pktq->getCount != NULL) { + qcnt = g_pktq->getCount(g_pktq); + if (qcnt > 0) { + packet = g_pktq->deq(g_pktq); + if (packet != NULL) { + g_ready_count--; + idle_count = 0; + TC_MUTEX_LOCK(&(packet->lock)); + g_ready_playbytes -= packet->byteCount; + g_ready_playtime = (g_ready_playbytes > 0) ? pa_bytes_to_usec(g_ready_playbytes, &sample_spec) / PA_USEC_PER_MSEC : 0; + g_ready_playtime *= 1; + plock = 1; + } + else { + reset_pktq(g_pktq); + } + } + else { + TC_MUTEX_UNLOCK(mutex_pktq); + TC_MUTEX_UNLOCK(mutex_ready); + idle_count++; + TC_MUTEX_LOCK(mutex_close); + done = g_received_close_pdu; + TC_MUTEX_UNLOCK(mutex_close); + continue; + } + } + TC_MUTEX_UNLOCK(mutex_pktq); + TC_MUTEX_UNLOCK(mutex_ready); + } + else { + if (g_pktq != NULL && g_pktq->deq != NULL && g_pktq->getCount != NULL) { + TC_MUTEX_LOCK(mutex_pktq); + qcnt = g_pktq->getCount(g_pktq); + if (qcnt > 0) { + packet = g_pktq->deq(g_pktq); + if (packet != NULL) { + g_ready_count--; + idle_count = 0; + TC_MUTEX_LOCK(&(packet->lock)); + g_ready_playbytes -= packet->byteCount; + g_ready_playtime = (g_ready_playbytes > 0) ? pa_bytes_to_usec(g_ready_playbytes, &sample_spec) / PA_USEC_PER_MSEC : 0; + g_ready_playtime *= 1; + plock = 1; + } + else { + reset_pktq(g_pktq); + } + } + TC_MUTEX_UNLOCK(mutex_pktq); + } + else { + MDBGLOG("sound","ERROR\t[%s()]: g_pktq = %p",__func__,g_pktq); + } + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: packet = %p, qcnt = %d",__func__,packet,qcnt); + MDBGLOG("sound","DEBUG\t[%s()]: g_ready_triggered = %d, g_ready_triggered_count = %d",__func__,g_ready_triggered,g_ready_triggered_count); + } + g_ready_triggered_count++; + g_ready_triggered = 0; + TC_MUTEX_UNLOCK(mutex_ready); + } + } + else { + TC_MUTEX_LOCK(mutex_up); + TC_MUTEX_LOCK(mutex_send); + if (g_sound_up > 0 && g_sound_ready_to_send > 0) { + TC_MUTEX_UNLOCK(mutex_send); + TC_MUTEX_UNLOCK(mutex_up); + TC_MUTEX_LOCK(mutex_pktq); + if (g_pktq != NULL && g_pktq->deq != NULL && g_pktq->getCount != NULL) { + qcnt = g_pktq->getCount(g_pktq); + if (qcnt > 0) { + packet = g_pktq->deq(g_pktq); + if (packet != NULL) { + g_ready_count--; + idle_count = 0; + TC_MUTEX_LOCK(&(packet->lock)); + plock = 1; + g_ready_playbytes -= packet->byteCount; + g_ready_playtime = (g_ready_playbytes > 0) ? pa_bytes_to_usec(g_ready_playbytes, &sample_spec) / PA_USEC_PER_MSEC : 0; + g_ready_playtime *= 1; + } + else { + reset_pktq(g_pktq); + } + } + else { + idle_count++; + } + } + else { + MDBGLOG("sound","ERROR\t[%s()]: g_pktq = %p",__func__,g_pktq); + } + TC_MUTEX_UNLOCK(mutex_pktq); + } + else { + TC_MUTEX_UNLOCK(mutex_send); + TC_MUTEX_UNLOCK(mutex_up); + } + } + TC_MUTEX_LOCK(mutex_up); + if (!g_sound_up || g_pktq == NULL || g_pktq->deq == NULL) { + TC_MUTEX_UNLOCK(mutex_up); + rv = 0; + } + else if (g_received_close_pdu == 0) { + TC_MUTEX_UNLOCK(mutex_up); + TC_MUTEX_LOCK(mutex_train); + if (g_sound_ready_to_train > 0 && g_trained < 1 && g_sound_ready_to_send < 1) { + g_sound_ready_to_train = 0; + trainAudio(); + g_trained = 1; + TC_MUTEX_UNLOCK(mutex_train); + idle_count = 0; + if (packet != NULL) { + if (packet->s[0] != NULL) { + g_free(packet->s[0]); + packet->s[0] = NULL; + } + if (packet->s[1] != NULL) { + g_free(packet->s[1]); + packet->s[1] = NULL; + } + g_free(packet); + packet = NULL; + } + TC_MUTEX_LOCK(mutex_close); + done = g_received_close_pdu; + TC_MUTEX_UNLOCK(mutex_close); + continue; + } + TC_MUTEX_LOCK(mutex_send); + if (g_sound_ready_to_send > 0 && packet != NULL) { + TC_MUTEX_UNLOCK(mutex_send); + TC_MUTEX_UNLOCK(mutex_train); + ls = (packet != NULL) ? packet->s[0] : NULL; + ms = (packet != NULL) ? packet->s[1] : NULL; + if (verbose) { + MDBGLOG("sound","DEBUG\t[%s()]: ls = %p, ms = %p",__func__,ls,ms); + } + if (ls == NULL) { + MDBGLOG("sound","WARNING\t[%s()]: ls is NULL",__func__); + } + else { + int ltime = 0; + size = (size_t)(ls->end - ls->data); + if (size > 0 && g_received_close_pdu < 1) { + if (ms != NULL && (ms->end - ms->data) > 0) { + size += (ms->end - ms->data); + } + if (g_enable_skew_compensation > 0 && !g_thunk) { + if (g_outstanding_playtime > g_target_latency && ((g_ready_count < 2) || (g_outstanding_playtime > g_target_latency && (g_ready_playtime < g_low_latency)))) { + unsigned char skipdelay = 0; + unsigned int tdelay = 0; + if (g_outstanding_playtime < g_min_latency && size > 20) { + //tdelay = (pa_bytes_to_usec(size - 20, &sample_spec) / PA_USEC_PER_MSEC) * 4; + tdelay = g_target_latency / 2; + } + else if (g_outstanding_playtime < g_lower_latency && size > 20) { + //tdelay = (pa_bytes_to_usec(size - 20, &sample_spec) / PA_USEC_PER_MSEC) * 3; + tdelay = g_target_latency / 3; + } + else if (g_outstanding_playtime < g_low_latency && size > 20) { + //tdelay = (pa_bytes_to_usec(size - 20, &sample_spec) / PA_USEC_PER_MSEC) * 2; + tdelay = g_target_latency / 4; + } + else { + //tdelay = (pa_bytes_to_usec(size - 20, &sample_spec) / PA_USEC_PER_MSEC) * 2; + tdelay = g_target_latency / 5; + } + if (skipdelay < 1) { + TC_MUTEX_LOCK(mutex_underrun); + g_underruns++; + g_most_recent_underrun_timestamp = g_time2(); + TC_MUTEX_UNLOCK(mutex_underrun); + } + if (tdelay > 19) { + g_sleep(tdelay); + } + } + else if (g_underruns > 0) { + long int tnow = g_time2(); + TC_MUTEX_LOCK(mutex_underrun); + if (g_underruns > 0 && g_most_recent_underrun_timestamp > 0 && (tnow - g_most_recent_underrun_timestamp) > g_high_latency) { + g_underruns = 0; + g_most_recent_underrun_timestamp = 0; + } + TC_MUTEX_UNLOCK(mutex_underrun); + } + } + if (size > 4) { + char * datas[2] = { NULL, NULL }; + size_t sizes[2] = { 0, 0 }; + const unsigned int num = 2; + + datas[0] = ls->data; + datas[1] = ((ms->end - ms->data) > 0) ? ms->data : NULL; + sizes[0] = (ls->end - ls->data); + sizes[1] = (ms->end - ms->data); + + MDBGLOG("sound","DEBUG\t[%s()]: *** SENDING ls (size = %d; cBlockNo = %d)",__func__,size,packet->cBlockNo); + TC_MUTEX_LOCK(mutex_out); + send_channel_data_multiple_atomic(g_rdpsnd_chan_id, num, datas, sizes); + TC_MUTEX_UNLOCK(mutex_out); + ltime = sound_get_local_time(); + TC_MUTEX_LOCK(mutex_pktlog); + if (pktlog[(packet->cBlockNo)].wOutTime == 0) { pktlog[(packet->cBlockNo)].wOutTime = ltime; } + pktlog[(packet->cBlockNo)].wTrueOutTime = ltime; + g_outstanding++; + g_outstanding_playbytes += size; + g_outstanding_playtime = (g_outstanding_playbytes > 0) ? pa_bytes_to_usec(g_outstanding_playbytes, &sample_spec) / PA_USEC_PER_MSEC : 0; + g_outstanding_playtime *= 1; + TC_MUTEX_UNLOCK(mutex_pktlog); + } + else { + MDBGLOG("sound","DEBUG\t[%s()]: *** SENDING ls (size = %d; cBlockNo = %d)",__func__,size,packet->cBlockNo); + TC_MUTEX_LOCK(mutex_out); + send_channel_data(g_rdpsnd_chan_id, ls->data, size); + TC_MUTEX_UNLOCK(mutex_out); + ltime = sound_get_local_time(); + TC_MUTEX_LOCK(mutex_pktlog); + if (pktlog[(packet->cBlockNo)].wOutTime == 0) { pktlog[(packet->cBlockNo)].wOutTime = ltime; } + pktlog[(packet->cBlockNo)].wTrueOutTime = ltime; + g_outstanding++; + g_outstanding_playbytes += size; + g_outstanding_playtime = (g_outstanding_playbytes > 0) ? pa_bytes_to_usec(g_outstanding_playbytes, &sample_spec) / PA_USEC_PER_MSEC : 0; + g_outstanding_playtime *= 1; + TC_MUTEX_UNLOCK(mutex_pktlog); + } + } + } + if (ls != NULL) { + if (ls->data != NULL) { + g_free(ls->data); + ls->data = NULL; + } + g_free(ls); + ls = NULL; + } + if (ms != NULL) { + if (ms->data != NULL) { + g_free(ms->data); + ms->data = NULL; + } + g_free(ms); + ms = NULL; + } + if (packet != NULL && plock > 0) { + if (packet->s[0] != NULL) { + packet->s[0] = NULL; + } + if (packet->s[1] != NULL) { + packet->s[1] = NULL; + } + if (plock > 0) { + TC_MUTEX_UNLOCK(&(packet->lock)); + } + TC_MUTEX_DEINIT(&(packet->lock)); + g_free(packet); + packet = (pkt *)NULL; + } + } + else { + if (g_trained == 0) { + g_sound_ready_to_train = 1; + } + TC_MUTEX_UNLOCK(mutex_send); + TC_MUTEX_UNLOCK(mutex_train); + } + rv = 0; + } + + + if (ls != NULL) { + free_stream(ls); + ls = NULL; + } + if (ms != NULL) { + free_stream(ms); + ms = NULL; + } + if (packet != NULL && plock > 0) { + if (packet->s[0] != NULL) { + packet->s[0] = NULL; + } + if (packet->s[1] != NULL) { + packet->s[1] = NULL; + } + if (plock > 0) { + TC_MUTEX_UNLOCK(&(packet->lock)); + } + TC_MUTEX_DEINIT(&(packet->lock)); + g_free(packet); + packet = (pkt *)NULL; + } + + TC_MUTEX_LOCK(mutex_close); + done = g_received_close_pdu; + TC_MUTEX_UNLOCK(mutex_close); + } + + exit:; + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: done. [%d, %d]",__func__,g_getpid(),g_gettid()); + } + TC_THREAD_EXIT(NULL); +} + +/*****************************************************************************/ +void * APP_CC +sound_inst(const char * cname) { + void * res = NULL; + + if (!g_strncmp(cname,"AUDIO_FORMAT",g_strlen(cname)) || !g_strncmp(cname,"WAVEFORMATEX",g_strlen(cname))) { + res = (void *)g_malloc(sizeof(AUDIO_FORMAT),1); + /* ((AUDIO_FORMAT *)res)->__destructor = &destroy_AUDIO_FORMAT; */ + construct_AUDIO_FORMAT(res); + } + else if (!g_strncmp(cname,"SNDTRAINING",g_strlen(cname))) { + res = (void *)g_malloc(sizeof(SNDTRAINING),1); + ((SNDTRAINING *)res)->__destructor = &destroy_SNDTRAINING; + construct_SNDTRAINING(res); + } + else if (!g_strncmp(cname,"SNDCLOSE",g_strlen(cname))) { + res = (void *)g_malloc(sizeof(SNDCLOSE),1); + ((SNDCLOSE *)res)->__destructor = &destroy_SNDCLOSE; + } + else if (!g_strncmp(cname,"SNDWAV",g_strlen(cname))) { + res = (void *)g_malloc(sizeof(SNDWAV),1); + ((SNDWAV *)res)->__destructor = &destroy_SNDWAV; + } + else if (!g_strncmp(cname,"SNDWAVINFO",g_strlen(cname))) { + res = (void *)g_malloc(sizeof(SNDWAVINFO),1); + ((SNDWAVINFO *)res)->__destructor = &destroy_SNDWAVINFO; + } + else if (!g_strncmp(cname,"SNDWAV_CONFIRM",g_strlen(cname))) { + res = (void *)g_malloc(sizeof(SNDWAV_CONFIRM),1); + ((SNDWAV_CONFIRM *)res)->__destructor = &destroy_SNDWAV_CONFIRM; + construct_SNDWAV_CONFIRM((SNDWAV_CONFIRM *)res); + } + else if (!g_strncmp(cname,"SNDTRAININGCONFIRM",g_strlen(cname))) { + res = (void *)g_malloc(sizeof(SNDTRAININGCONFIRM),1); + ((SNDTRAININGCONFIRM *)res)->__destructor = &destroy_SNDTRAININGCONFIRM; + construct_SNDTRAININGCONFIRM((SNDTRAININGCONFIRM *)res); + } + else if (!g_strncmp(cname,"CLIENT_AUDIO_VERSION_AND_FORMATS",g_strlen(cname))) { + res = (void *)g_malloc(sizeof(CLIENT_AUDIO_VERSION_AND_FORMATS),1); + ((CLIENT_AUDIO_VERSION_AND_FORMATS *)res)->__destructor = &destroy_CLIENT_AUDIO_VERSION_AND_FORMATS; + construct_CLIENT_AUDIO_VERSION_AND_FORMATS(res); + } + else if (!g_strncmp(cname,"SERVER_AUDIO_VERSION_AND_FORMATS",g_strlen(cname))) { + res = (void *)g_malloc(sizeof(SERVER_AUDIO_VERSION_AND_FORMATS),1); + ((SERVER_AUDIO_VERSION_AND_FORMATS *)res)->__destructor = &destroy_SERVER_AUDIO_VERSION_AND_FORMATS; + } + else if (!g_strncmp(cname,"QUALITY_MODE",g_strlen(cname))) { + res = (void *)g_malloc(sizeof(QUALITY_MODE),1); + ((QUALITY_MODE *)res)->__destructor = &destroy_QUALITY_MODE; + construct_QUALITY_MODE(res); + } + else if (!g_strncmp(cname,"pktq",g_strlen(cname))) { + res = (void *)g_malloc(sizeof(pktq),1); + ((pktq *)res)->__destructor = &destroy_pktq; + construct_pktq(res); + } + return res; +} + + +/*****************************************************************************/ +static size_t APP_CC +sound_queue_packet(void * data, size_t len) { + size_t rv = 0; + struct stream * ls = (struct stream *)NULL; + struct stream * ms = (struct stream *)NULL; + SNDWAVINFO * pdu = (SNDWAVINFO *)NULL; + int chunk_size = 0; + unsigned char bad = 0; + double dur = 0.; + WORD bno = 0; + BYTE buf[1] = { 1 }; + + if (g_received_close_pdu > 0) { + goto end; + } + + if (data == NULL || len < 1) { + MDBGLOG("sound","WARNING\t[%s()]: data = %p; len = %d",__func__,data,len); + goto end; + } + + TC_MUTEX_LOCK(mutex_pktq); + if (g_pktq == NULL) { + TC_MUTEX_UNLOCK(mutex_pktq); + MDBGLOG("sound","ERROR\t[%s()]: g_pktq is NULL",__func__); + goto end; + } + else { + TC_MUTEX_UNLOCK(mutex_pktq); + } + + TC_MUTEX_LOCK(mutex_send); + if (g_sound_ready_to_send < 1) { + TC_MUTEX_UNLOCK(mutex_send); + goto end; + } + else { + TC_MUTEX_UNLOCK(mutex_send); + } + + TC_MUTEX_LOCK(mutex_close); + if (g_received_close_pdu > 0) { + TC_MUTEX_UNLOCK(mutex_close); + goto end; + } + else { + TC_MUTEX_UNLOCK(mutex_close); + } + + chunk_size = len; + + pdu = (SNDWAVINFO *)g_malloc(sizeof(SNDWAVINFO), 1); + if (pdu == NULL) { + MDBGLOG("sound","ERROR\t[%s()]: pdu is NULL",__func__); + goto end; + } + else { + pdu->__destructor = &destroy_SNDWAVINFO; + } + + make_stream(ls); + make_stream(ms); + if (ls == NULL || ms == NULL) { + MDBGLOG("sound","ERROR\t[%s()]: failed to create stream",__func__); + goto wrapup; + } + init_stream(ls, MAX_STREAM); + init_stream(ms, MAX_STREAM); + + TC_MUTEX_LOCK(mutex_formats); + construct_SNDWAVINFO(pdu,g_client_format_index,chunk_size,(BYTE *)(data)); + if (pdu->alen > (MAX_PDU_LENGTH - 16)) { + pdu->alen =(MAX_PDU_LENGTH - 16); + } + if (pdu->alen > 0 && g_format_byte_rate > 0) { + dur = (0. + (pdu->alen - 4)) / (0. + g_format_byte_rate); + } + else if (g_format_byte_rate > 0) { + dur = 4. / (0. + g_format_byte_rate); + } + TC_MUTEX_UNLOCK(mutex_formats); + if ((pdu->alen + 12) > MAX_PDU_LENGTH) { + MDBGLOG("sound","ERROR\t[%s()]: !!! pdu->alen is greater than MAX_PDU_LENGTH !!!",__func__); + bad = 1; + } + else if ((pdu->appendix == NULL) || !(pdu->alen > 0)) { + MDBGLOG("sound","ERROR\t[%s()]: !!! pdu->appendix = %p, pdu->alen = %d !!!",__func__,pdu->appendix,pdu->alen); + //bad = 1; + } + if (bad) { + rv = 0; + goto wrapup; + } + else { + TC_MUTEX_LOCK(mutex_block); + pdu->cBlockNo = g_current_block++; + TC_MUTEX_UNLOCK(mutex_block); + bno = pdu->cBlockNo; + sound_SNDWAVINFO_out(ls, pdu); + s_mark_end(ls); + if (pdu->alen > 4) { + sound_SNDWAV_out(ms, pdu->appendix, pdu->alen); + s_mark_end(ms); + } + else { + free_stream(ms); + ms = (struct stream *)NULL; + } + } + + TC_MUTEX_LOCK(mutex_pktq); + if (g_pktq != NULL && g_pktq->enq != NULL && chunk_size > 0 && pdu != NULL && pdu->alen > 4 && ls != NULL && ms != NULL && pdu->cBlockNo > -1 && pdu->cBlockNo < MAX_PKTLOG) { + pkt * tpkt = (pkt *)NULL; + tpkt = (pkt *)g_malloc(sizeof(pkt),1); + TC_MUTEX_INIT(&(tpkt->lock),g_attr); + TC_MUTEX_LOCK(&(tpkt->lock)); + tpkt->magic = PKT_MAGIC; + tpkt->s[0] = ls; + tpkt->s[1] = ms; + tpkt->byteCount = pdu->alen; + tpkt->duration = dur; + tpkt->cBlockNo = bno; + tpkt->next = NULL; + tpkt->prev = NULL; + TC_MUTEX_UNLOCK(&(tpkt->lock)); + g_pktq->enq(g_pktq, tpkt); + TC_MUTEX_LOCK(mutex_pktlog); + rv = chunk_size; + //rv = pdu->alen; + g_memset(&(pktlog[(pdu->cBlockNo)]),0,sizeof(pktinfo)); + pktlog[(pdu->cBlockNo)].bSize = pdu->Header.BodySize; + pktlog[(pdu->cBlockNo)].wAckTime = 0; + pktlog[(pdu->cBlockNo)].wOutTime = pdu->wTimeStamp; + pktlog[(pdu->cBlockNo)].dwLength = rv; + TC_MUTEX_UNLOCK(mutex_pktlog); + ls = NULL; + ms = NULL; + tpkt = NULL; + if (tpkt != NULL) { + g_free(tpkt); + tpkt = NULL; + } + } + TC_MUTEX_UNLOCK(mutex_pktq); + + wrapup:; + if (ls != NULL) { + if (ls->data != NULL) { + g_free(ls->data); + ls->data = NULL; + } + g_free(ls); + ls = NULL; + } + if (ms != NULL) { + if (ms->data != NULL) { + g_free(ms->data); + ms->data = NULL; + } + g_free(ms); + ms = NULL; + } + if (pdu != NULL) { + if (0 && pdu->__destructor != NULL) { + pdu->__destructor(pdu); + pdu = NULL; + } + else { + if (pdu->appendix != NULL) { + if (0 && pdu->appendix->__destructor != NULL) { + pdu->appendix->__destructor(pdu->appendix); + } + else { + g_free(pdu->appendix); + } + pdu->appendix = NULL; + } + g_free(pdu); + pdu = NULL; + } + } + + end:; + return rv; +} + + +/*****************************************************************************/ +static int APP_CC +sound_estimate_latency(void) { + int rv = 0; + int idx = 0; + int lmt = MAX_PKTLOG; + int count = 0; + long total = 0; + + TC_MUTEX_LOCK(mutex_pktlog); + TC_MUTEX_LOCK(mutex_formats); + for (idx = 0; idx < lmt; idx++) { + if ((pktlog[idx].wOutTime != 0) && (pktlog[idx].wAckTime != 0)) { + if (pktlog[idx].wAckTime > pktlog[idx].wOutTime) { + //total += (pktlog[idx].wAckTime - pktlog[idx].wOutTime) / pktlog[idx].bSize; + total += ((pktlog[idx].wAckTime - pktlog[idx].wOutTime) - (g_format_byte_rate / pktlog[idx].bSize)) / pktlog[idx].bSize; + } + else { + total += ((pktlog[idx].wAckTime + (65536 - pktlog[idx].wOutTime)) - (g_format_byte_rate / pktlog[idx].bSize)) / pktlog[idx].bSize; + } + count++; + } + } + TC_MUTEX_UNLOCK(mutex_formats); + TC_MUTEX_UNLOCK(mutex_pktlog); + if (count > 0) { + if (total == 0) { + rv = 0; + } + else { + rv = total / count; + } + } + + MDBGLOG("sound"," ** [sound_estimate_latency()] total = %ld; count = %d; rv = %d\0",total,count,rv); + + return rv; +} + +/***************************************************************************** + * + * Must be called only while the caller holds "self->lock" mutex; + * "itm" must already be fully initialized (including "itm->lock" mutex). + */ +static int APP_CC +q_enq(pktq * self, pkt * in_itm) { + int rv = 0; + int cnt = 0; + pkt * itm = (pkt *)NULL; + assert(self); + assert(in_itm); + assert(in_itm->magic == PKT_MAGIC); + if (self->count == self->max) { + MDBGLOG("sound","ERROR\t[%s()]: <<< queue is full >>>",__func__); + rv = -1; + TC_MUTEX_UNLOCK(mutex_pktq); + if (g_idle > 0 && cond_ready != NULL && g_ready_waiting > 0) { + TC_MUTEX_LOCK(mutex_ready); + g_ready_triggered = 1; + MDBGLOG("sound","DEBUG\t[%s()]: <<< SIGNALING cond_ready >>>",__func__); + if (g_ready_waiting > 0) { + TC_COND_BROADCAST(cond_ready); + } + else { + TC_COND_SIGNAL(cond_ready); + } + TC_MUTEX_UNLOCK(mutex_ready); + } + else { + reset_pktq(g_pktq); + } + goto end; + } + TC_MUTEX_LOCK(&(in_itm->lock)); + itm = in_itm; + if (self->top > self->bottom) { + cnt = (self->top - self->bottom) + 1; + if (cnt < self->max) { + if (self->top < (self->max - 1)) { + self->top++; + } + else { + self->top = 0; + } + if (self->items[self->top] == NULL) { + self->items[self->top] = itm; + } + else { + rv = -2; + } + } + else { + rv = -1; + } + } + else if (self->top == self->bottom) { + if (self->items[self->top] == NULL) { + self->items[self->top] = itm; + } + else { + if (self->top < (self->max - 1)) { + self->top++; + } + else { + self->top = 0; + } + if (self->items[self->top] == NULL) { + self->items[self->top] = itm; + } + else { + rv = -5; + } + } + } + else { + cnt = (self->top + 1) + (self->max - self->bottom); + if (cnt < self->max) { + if (self->top < (self->max - 1)) { + self->top++; + } + else { + self->top = 0; + } + if (self->items[self->top] == NULL) { + self->items[self->top] = itm; + } + else { + rv = -6; + } + } + else { + rv = -3; + } + } + TC_MUTEX_UNLOCK(&(itm->lock)); + self->count++; + end:; + return rv; +} + +/*****************************************************************************/ +static pkt * APP_CC +q_deq(pktq * self) { + pkt * rv = (pkt *)NULL; + if (self->top != self->bottom) { + rv = self->items[self->bottom]; + self->items[self->bottom] = (pkt *)NULL; + if (self->bottom < (MAX_PKTQ - 1)) { + self->bottom++; + } + else { + self->bottom = 0; + } + } + else if (self->items[self->bottom] != NULL) { + rv = self->items[self->bottom]; + self->items[self->bottom] = (pkt *)NULL; + } + self->count--; + return rv; +} + +/*****************************************************************************/ +static int APP_CC +q_getCount(pktq * self) { + int rv = 0; + if (g_pktq != NULL) { + rv = g_pktq->count; + } + return rv; +} + +/*****************************************************************************/ +static int APP_CC +q_getCount_old(pktq * self) { + int rv = 0; + + //TC_MUTEX_LOCK(mutex_sound); + + if (self->top > self->bottom) { + rv = (self->top - self->bottom) + 1; + } + else if (self->top == self->bottom) { + if (self->items[self->top] != NULL) { + rv = 1; + } + } + else { + rv = (self->top + 1) + (MAX_PKTQ - self->bottom); + } + + //TC_MUTEX_UNLOCK(mutex_sound); + return rv; +} + +/*****************************************************************************/ +static int APP_CC +q_getMax(pktq * self) { + int rv = 0; + + rv = self->max; + + return rv; +} + +/*****************************************************************************/ +static int APP_CC +q_setMax(pktq * self, int ival) { + int rv = 0; + + //TC_MUTEX_LOCK(mutex_sound); + + if ((ival < (MAX_PKTQ + 1)) && (ival > -1)) { + self->max = ival; + } + else { + rv = -1; + } + + //TC_MUTEX_UNLOCK(mutex_sound); + + return rv; +} + +/*****************************************************************************/ +static int APP_CC +q_getMin(pktq * self) { + int rv = 0; + + rv = self->min; + + return rv; +} + +/*****************************************************************************/ +static int APP_CC +q_setMin(pktq * self, int ival) { + int rv = 0; + + if ((ival < (MAX_PKTQ + 1)) && (ival > -1) && (ival <= self->max)) { + self->min = ival; + } + else { + rv = -1; + } + + return rv; +} + +/*****************************************************************************/ +static unsigned int APP_CC +q_ready(pktq * self) { + unsigned int rv = 0; + + //TC_MUTEX_LOCK(mutex_sound); + + if (self->getCount(self) > self->min) { + rv = 1; + } + + //TC_MUTEX_UNLOCK(mutex_sound); + return rv; +} + +/*****************************************************************************/ +static void APP_CC +destroy_pktq(pktq * self) { + + //TC_MUTEX_LOCK(mutex_sound); + //g_free(self); + //TC_MUTEX_UNLOCK(mutex_sound); + +} + +/************************************************************************/ +/* This is called whenever new data is available */ +static void APP_CC stream_read_callback(pa_stream * s, size_t length, void * userdata) { + int rdy = 0; + int rdytime = 0; + size_t idx = 0; + size_t olen = 0; + size_t rsize = 0; + unsigned int lqueued = 0; + unsigned int qcnt = 0; + const void * data = (const void *)NULL; + unsigned char skip = 0; + unsigned char mlock = 0; + unsigned char peeked = 0; + unsigned char hopper_pending = 0; + unsigned char l_free_data = 0; + pa_stream_state_t ss; + + assert(s); + assert(length > 0); + + olen = length; + + TC_MUTEX_LOCK(mutex_event); + if (stdio_event) { + mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); + } + TC_MUTEX_UNLOCK(mutex_event); + + TC_MUTEX_LOCK(mutex_stream); + + if (s == NULL || length < 1) { + TC_MUTEX_UNLOCK(mutex_stream); + MDBGLOG("sound","ERROR\t[%s()]: s is NULL or length is zero (s = %p, length = %d)",__func__,s,length); + goto end; + } + + g_memset(&ss,0,sizeof(pa_stream_state_t)); + ss = pa_stream_get_state(s); + if (ss != PA_STREAM_READY) { + TC_MUTEX_UNLOCK(mutex_stream); + MDBGLOG("sound","DEBUG\t[%s()]: stream is not ready",__func__); + goto end; + } + + rsize = pa_stream_readable_size(s); + while (rsize > 0) { + size_t tlen = 0; + unsigned int idx = 0; + unsigned char empty = 1; + + peeked = 0; + length = rsize; + data = (void *)NULL; + hopper_pending = (g_hopper_length < 1) ? 0 : 1; + + g_memset(&ss,0,sizeof(pa_stream_state_t)); + ss = pa_stream_get_state(s); + if (ss != PA_STREAM_READY) { + TC_MUTEX_UNLOCK(mutex_stream); + MDBGLOG("sound","ERROR\t[%s()]: stream is not ready",__func__); + break; + } + else if (pa_stream_peek(s, &data, &length) < 0) { + TC_MUTEX_UNLOCK(mutex_stream); + MDBGLOG("sound", "ERROR\t[%s()]: pa_stream_peek() failed: %s", __func__, pa_strerror(pa_context_errno(context))); + pa_quit(1); + return; + } + + peeked = 1; + tlen = length; + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: length = %d",__func__,length); + } + + TC_MUTEX_LOCK(mutex_up); + TC_MUTEX_LOCK(mutex_ready); + if ((g_sound_up < 1 || g_stream_ready < 1) || (g_enable_skew_compensation > 0 && (g_thunk == 0) && ((g_ready_count >= (MAX_PKTLOG / 3)) || (g_ready_playtime > g_target_latency)))) { + TC_MUTEX_UNLOCK(mutex_ready); + TC_MUTEX_UNLOCK(mutex_up); + TC_MUTEX_LOCK(mutex_pktq); + reset_pktq(g_pktq); + TC_MUTEX_UNLOCK(mutex_pktq); + goto drop; + } + else { + g_thunk = 0; + TC_MUTEX_UNLOCK(mutex_ready); + TC_MUTEX_UNLOCK(mutex_up); + } + + length = MIN(length, ((MAX_PDU_LENGTH - 16) - g_hopper_length)); + + empty = 1; + if (g_drop_silence) { + if ((length % 8) == 0) { + uint64_t * tbuf = (uint64_t *)data; + for (idx = 0; idx < (length / 8); idx++) { + if (tbuf[idx] != 0) { + empty = 0; + break; + } + } + } + else if ((length % 4) == 0) { + uint32_t * tbuf = (uint32_t *)data; + for (idx = 0; idx < (length / 4); idx++) { + if (tbuf[idx] != 0) { + empty = 0; + break; + } + } + } + else if ((length % 2) == 0) { + uint16_t * tbuf = (uint16_t *)data; + for (idx = 0; idx < (length / 2); idx++) { + if (tbuf[idx] != 0) { + empty = 0; + break; + } + } + } + else { + uint8_t * tbuf = (uint8_t *)data; + for (idx = 0; idx < length; idx++) { + if (tbuf[idx] != 0) { + empty = 0; + break; + } + } + } + } + + if (empty > 0 && hopper_pending == 0 && length > ((MAX_PDU_LENGTH / 2) - 10)) { + if (verbose) { + MDBGLOG("sound","DEBUG\t[%s()]: ((( EMPTY )))",__func__); + } + TC_MUTEX_LOCK(mutex_pktq); + reset_pktq(g_pktq); + TC_MUTEX_UNLOCK(mutex_pktq); + goto drop; + } + + TC_MUTEX_LOCK(mutex_buffer); + + if (length <= ((MAX_PDU_LENGTH / 2) - 10)) { + if (g_hopper_length == 0) { + g_memcpy(g_hopper, data, MIN(length,MAX_STREAM)); + g_hopper_length = length; + TC_MUTEX_UNLOCK(mutex_buffer); + hopper_pending = 1; + goto drop; + } + else if ((MAX_STREAM - g_hopper_length) > 0) { + g_memcpy((g_hopper + g_hopper_length), data, MIN(length,(MAX_STREAM - g_hopper_length))); + g_hopper_length += length; + length = g_hopper_length; + data = g_hopper; + if (length <= ((MAX_PDU_LENGTH / 2) - 10)) { + TC_MUTEX_UNLOCK(mutex_buffer); + hopper_pending = 1; + goto drop; + } + else { + g_hopper_length = 0; + hopper_pending = 0; + } + } + } + + if (skip == 0 && data != NULL && g_sound_up > 0 && g_stream_ready > 0) { + switch (g_preferred_wave_format) { + case WAVE_FORMAT_MPEGLAYER3: + break; + case WAVE_FORMAT_GSM610: + break; + case WAVE_FORMAT_MSG723: + break; + case WAVE_FORMAT_IMA_ADPCM: + { + uint8_t * dst = g_malloc(length, 1); + // length = sound_convert_pcm_to_ima_adpcm(dst, length, data, length); + data = dst; + l_free_data = 1; + } + break; + case WAVE_FORMAT_ADPCM: + break; + case WAVE_FORMAT_PCM: + default: + break; + } + if (skip == 0) while (length > 0) { + size_t rv = 0; + if (g_preferred_wave_format == WAVE_FORMAT_PCM) { + rv = (length % 2 == 0) ? sound_queue_packet((uint8_t*)(data+idx), MIN(length, MAX_PDU_LENGTH - 16)) : MIN(length, MAX_PDU_LENGTH - 16); + } + else if (g_preferred_wave_format == WAVE_FORMAT_IMA_ADPCM) { + unsigned int rem = length % 4; + if (rem > 0) { + length += (4 - rem); + } + rv = sound_queue_packet((uint8_t*)(data+idx), MIN(length, MAX_PDU_LENGTH - 16)); + } + else { + rv = (length % 2 == 0) ? sound_queue_packet((uint8_t*)(data+idx), MIN(length, MAX_PDU_LENGTH - 16)) : MIN(length, MAX_PDU_LENGTH - 16); + } + idx += rv; + length -= rv; + if (rv > 0) { + lqueued++; + } + else if (rv == 0) { + break; + } + } + } + + TC_MUTEX_UNLOCK(mutex_buffer); + + if (lqueued > 0) { + TC_MUTEX_LOCK(mutex_ready); + g_ready_count += lqueued; + g_ready_playbytes += length; + g_ready_playtime = (g_ready_playbytes > 0) ? pa_bytes_to_usec(g_ready_playbytes, &sample_spec) / PA_USEC_PER_MSEC : 0; + g_ready_playtime *= 1; + TC_MUTEX_LOCK(mutex_pktq); + if (g_pktq != NULL && g_pktq->head != NULL && g_pktq->getCount != NULL) { + qcnt = g_pktq->getCount(g_pktq); + } + TC_MUTEX_UNLOCK(mutex_pktq); + if (g_idle > 0 && cond_ready != NULL && g_ready_waiting > 0 && g_ready_count > 0 && g_ready_playtime >= (g_target_latency / 2)) { + g_ready_triggered = 1; + if (g_ready_waiting > 0) { + TC_COND_BROADCAST(cond_ready); + } + else { + TC_COND_SIGNAL(cond_ready); + } + } + TC_MUTEX_UNLOCK(mutex_ready); + } + + drop:; + if (tlen > 0 && peeked > 0) { + pa_stream_drop(s); + } + + if (l_free_data > 0 && data != NULL && data != g_hopper) { + g_free((void *)data); + } + + rsize = pa_stream_readable_size(s); + } + + signal:; + TC_MUTEX_LOCK(mutex_drain); + if ((g_drain > 0) && (g_outstanding_playtime <= g_target_latency)) { + TC_MUTEX_LOCK(mutex_pktq); + reset_pktq(g_pktq); + TC_MUTEX_UNLOCK(mutex_pktq); + TC_COND_SIGNAL(mutex_drain); + TC_MUTEX_UNLOCK(mutex_drain); + } + else { + TC_MUTEX_UNLOCK(mutex_drain); + } + + TC_MUTEX_LOCK(mutex_ready); + if (g_idle > 0 && cond_ready != NULL && g_ready_waiting > 0 && g_ready_count > 0) { + g_ready_triggered = 1; + if (g_ready_waiting > 0) { + TC_COND_BROADCAST(cond_ready); + } + else { + TC_COND_SIGNAL(cond_ready); + } + } + TC_MUTEX_UNLOCK(mutex_ready); + + end:; + TC_MUTEX_UNLOCK(mutex_stream); + return; +} + +/*****************************************************************************/ +/* This routine is called whenever the sink state changes */ +static void APP_CC pa_sink_state_callback(struct pa_context * c, const pa_sink_info * s, void * userdata) { + const char * sname = (s->name == NULL || g_strlen(s->name) < 1) ? "" : s->name; + const char * dname = (s->driver == NULL || g_strlen(s->driver) < 1) ? "" : s->driver; + if (s == NULL) { + goto end; + } + else switch (s->state) { + case PA_SINK_RUNNING: + { + MDBGLOG("sound","INFO\t[%s()]: PA_SINK_RUNNING (name: %s, driver: %s)", __func__, sname, dname); + if (g_sound_up < 1) { + TC_MUTEX_LOCK(mutex_up); + g_sound_up = 1; + TC_MUTEX_UNLOCK(mutex_up); + } + } + break; + case PA_SINK_IDLE: + { + MDBGLOG("sound","INFO\t[%s()]: PA_SINK_IDLE (name: %s, driver: %s)", __func__, sname, dname); + if (g_sound_up < 1) { + TC_MUTEX_LOCK(mutex_up); + g_sound_up = 1; + TC_MUTEX_UNLOCK(mutex_up); + } + } + break; + case PA_SINK_SUSPENDED: + { + MDBGLOG("sound","INFO\t[%s()]: PA_SINK_SUSPENDED (name: %s, driver: %s)", __func__, sname, dname); + if (g_sound_up < 1) { + TC_MUTEX_LOCK(mutex_up); + if (g_sound_up < 1) { + g_sound_up = 1; + } + TC_MUTEX_UNLOCK(mutex_up); + } + } + break; + case PA_SINK_INVALID_STATE: + default: + { + MDBGLOG("sound","INFO\t[%s()]: PA_SINK_INVALID_STATE (name: %s, driver: %s)", __func__, sname, dname); + if (g_sound_up > 0) { + TC_MUTEX_LOCK(mutex_up); + if (g_sound_up > 0) { + g_sound_up = 0; + } + TC_MUTEX_UNLOCK(mutex_up); + } + } + break; + } + end:; + return; +} + + +/*****************************************************************************/ +/* This routine is called whenever the sink state changes */ +static void APP_CC pa_source_state_callback(struct pa_context * c, const pa_source_info * s, void * userdata) { + const char * sname = (s->name == NULL || g_strlen(s->name) < 1) ? "" : s->name; + const char * dname = (s->driver == NULL || g_strlen(s->driver) < 1) ? "" : s->driver; + if (s == NULL) { + goto end; + } + else switch (s->state) { + case PA_SOURCE_RUNNING: + { + MDBGLOG("sound","INFO\t[%s()]: PA_SOURCE_RUNNING (name: %s, driver: %s)", __func__, sname, dname); + if (g_sound_up < 1) { + TC_MUTEX_LOCK(mutex_up); + g_sound_up = 1; + TC_MUTEX_UNLOCK(mutex_up); + } + } + break; + case PA_SOURCE_IDLE: + { + MDBGLOG("sound","INFO\t[%s()]: PA_SOURCE_IDLE (name: %s, driver: %s)", __func__, sname, dname); + if (g_sound_up < 1) { + TC_MUTEX_LOCK(mutex_up); + g_sound_up = 1; + TC_MUTEX_UNLOCK(mutex_up); + } + } + break; + case PA_SOURCE_SUSPENDED: + { + MDBGLOG("sound","INFO\t[%s()]: PA_SOURCE_SUSPENDED (name: %s, driver: %s)", __func__, sname, dname); + if (g_sound_up < 1) { + TC_MUTEX_LOCK(mutex_up); + if (g_sound_up < 1) { + g_sound_up = 1; + } + TC_MUTEX_UNLOCK(mutex_up); + } + } + break; + case PA_SOURCE_INVALID_STATE: + default: + { + MDBGLOG("sound","INFO\t[%s()]: PA_SOURCE_INVALID_STATE (name: %s, driver: %s)", __func__, sname, dname); + if (g_sound_up > 0) { + TC_MUTEX_LOCK(mutex_up); + if (g_sound_up > 0) { + g_sound_up = 0; + } + TC_MUTEX_UNLOCK(mutex_up); + } + } + break; + } + end:; + return; +} + + +/*****************************************************************************/ +/* This routine is called whenever the stream state changes */ +static void APP_CC stream_state_callback(pa_stream * s, void * userdata) { + int sstate = 0; + unsigned char mlock = 0; + pa_stream_state_t state; + const pa_sample_spec * ss = (const pa_sample_spec *)NULL; + + assert(s); + + g_memset(&state,0,sizeof(pa_stream_state_t)); + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called (s = %p)",__func__,s); + } + + TC_MUTEX_LOCK(mutex_stream); + + state = pa_stream_get_state(s); + + switch (state) { + case PA_STREAM_CREATING: + { + if (verbose) { + MDBGLOG("sound", "INFO\t[%s()]: PA_STREAM_CREATING", __func__); + } + } + break; + case PA_STREAM_TERMINATED: + { + if (verbose) { + MDBGLOG("sound", "INFO\t[%s()]: PA_STREAM_TERMINATED", __func__); + } + } + break; + + case PA_STREAM_READY: + { + char cmt[PA_CHANNEL_MAP_SNPRINT_MAX], sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; + const pa_buffer_attr * a = (const pa_buffer_attr *)NULL; + if (verbose) { + MDBGLOG("sound", "INFO\t[%s()]: PA_STREAM_READY (Stream successfully created).", __func__); + } + if (!(a = pa_stream_get_buffer_attr(s))) { + MDBGLOG("sound", "INFO\t[%s()]: pa_stream_get_buffer_attr() failed (\"%s\")", __func__, pa_strerror(pa_context_errno(pa_stream_get_context(s)))); + } + else { + ss = pa_stream_get_sample_spec(s); + if (verbose > 0 && mode == PLAYBACK) { + MDBGLOG("sound", "INFO\t[%s()]: Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u", __func__, a->maxlength, a->tlength, a->prebuf, a->minreq); + } + else if (verbose > 0) { + assert(mode == RECORD); + MDBGLOG("sound", "INFO\t[%s()]: Buffer metrics: maxlength=%u, fragsize=%u", __func__, a->maxlength, a->fragsize); + } + } + if (verbose) { + MDBGLOG("sound", "INFO\t[%s()]: Using sample spec '%s', channel map '%s'.", __func__, + pa_sample_spec_snprint(sst, sizeof(sst), pa_stream_get_sample_spec(s)), + pa_channel_map_snprint(cmt, sizeof(cmt), pa_stream_get_channel_map(s))); + MDBGLOG("sound", "INFO\t[%s()]: Connected to device %s (%u, %ssuspended).", + __func__, + pa_stream_get_device_name(s), + pa_stream_get_device_index(s), + pa_stream_is_suspended(s) ? "" : "not "); + } + } + break; + case PA_STREAM_FAILED: + default: + { + MDBGLOG("sound", "INFO\t[%s()]: Stream error: %s", __func__, pa_strerror(pa_context_errno(pa_stream_get_context(s)))); + if (mutex_stream_ready != NULL) { + TC_MUTEX_LOCK(mutex_stream_ready); + g_stream_ready = 0; + TC_MUTEX_UNLOCK(mutex_stream_ready); + } + pa_quit(1); + goto end; + } + } + + if (state == PA_STREAM_READY) { + unsigned char plock = 0; + pa_operation * op = (pa_operation *)NULL; + if (mutex_up != NULL) { + TC_MUTEX_LOCK(mutex_up); + if (g_sound_up < 1) { + g_sound_up = 1; + } + TC_MUTEX_UNLOCK(mutex_up); + } + if (mutex_stream_ready != NULL && cond_stream_ready != NULL) { + TC_MUTEX_LOCK(mutex_stream_ready); + if (g_stream_ready < 1) { + g_stream_ready = 1; + TC_COND_SIGNAL(cond_stream_ready); + } + TC_MUTEX_UNLOCK(mutex_stream_ready); + } + if (!pa_threaded_mainloop_in_thread(mt)) { + pa_threaded_mainloop_lock(mt); + plock = 1; + } + if (!(op = pa_stream_flush(s, NULL, NULL))) { + MDBGLOG("sound", "ERROR\t[%s()]: pa_stream_flush() -> \"%s\"", __func__, pa_strerror(pa_context_errno(context))); + if (plock > 0) { + pa_threaded_mainloop_unlock(mt); + plock = 0; + } + } + TC_MUTEX_LOCK(mutex_pktq); + reset_pktq(g_pktq); + TC_MUTEX_UNLOCK(mutex_pktq); + if (op != NULL) { + pa_operation_unref(op); + op = NULL; + } + if (pa_stream_is_corked(s) && !(op = pa_stream_cork(s, 0, NULL, NULL))) { + MDBGLOG("sound", "ERROR\t[%s()]: pa_stream_cork() -> \"%s\"", __func__, pa_strerror(pa_context_errno(context))); + if (plock > 0) { + pa_threaded_mainloop_unlock(mt); + plock = 0; + } + TC_MUTEX_UNLOCK(mutex_stream); + pa_quit(1); + return; + } + if (op != NULL) { + pa_operation_unref(op); + op = NULL; + } + if (plock > 0) { + pa_threaded_mainloop_unlock(mt); + plock = 0; + } + } + else { + unsigned char plock = 0; + pa_operation * op = (pa_operation *)NULL; + if (!pa_stream_is_corked(s) && !(op = pa_stream_cork(s, 1, NULL, NULL))) { + MDBGLOG("sound", "ERROR\t[%s()]: pa_stream_cork() -> \"%s\"", __func__, pa_strerror(pa_context_errno(context))); + if (plock > 0) { + pa_threaded_mainloop_unlock(mt); + plock = 0; + } + TC_MUTEX_UNLOCK(mutex_stream); + pa_quit(1); + return; + } + if (op != NULL) { + pa_operation_unref(op); + op = NULL; + } + if (mutex_up != NULL) { + TC_MUTEX_LOCK(mutex_up); + if (g_sound_up > 0) { + g_sound_up = 0; + start_drain_noquit(); + } + TC_MUTEX_UNLOCK(mutex_up); + } + TC_MUTEX_LOCK(mutex_stream_ready); + g_stream_ready = 0; + TC_MUTEX_UNLOCK(mutex_stream_ready); + if (!pa_threaded_mainloop_in_thread(mt)) { + pa_threaded_mainloop_lock(mt); + plock = 1; + } + if (g_sound_up > 0 && !(op = pa_stream_flush(s, NULL, NULL))) { + MDBGLOG("sound", "ERROR\t[%s()]: pa_stream_flush() -> \"%s\"", __func__, pa_strerror(pa_context_errno(context))); + if (plock > 0) { + pa_threaded_mainloop_unlock(mt); + plock = 0; + } + TC_MUTEX_UNLOCK(mutex_stream); + pa_quit(1); + return; + } + TC_MUTEX_LOCK(mutex_pktq); + reset_pktq(g_pktq); + TC_MUTEX_UNLOCK(mutex_pktq); + if (op != NULL) { + pa_operation_unref(op); + op = NULL; + } + if (plock > 0) { + pa_threaded_mainloop_unlock(mt); + plock = 0; + } + } + + end:; + TC_MUTEX_UNLOCK(mutex_stream); + return; +} + +/*****************************************************************************/ +static void APP_CC stream_event_callback(pa_stream * s, const char * name, pa_proplist * pl, void * userdata) { + char * t = (char *)NULL; + + TC_MUTEX_LOCK(mutex_stream); + + assert(s); + assert(name); + assert(pl); + + t = pa_proplist_to_string_sep(pl, ", "); + MDBGLOG("sound", "INFO\t[%s()]: Got event '%s', properties '%s'", __func__, name, t); + pa_xfree(t); + + TC_MUTEX_UNLOCK(mutex_stream); +} + +/*****************************************************************************/ +static void APP_CC stream_started_callback(pa_stream * s, void * userdata) { + + TC_MUTEX_LOCK(mutex_stream); + + assert(s); + + //if (verbose) { + MDBGLOG("sound", "INFO\t[%s()]: Stream started.", __func__); + //} + + TC_MUTEX_UNLOCK(mutex_stream); +} + +/*****************************************************************************/ +static void APP_CC stream_moved_callback(pa_stream * s, void * userdata) { + TC_MUTEX_LOCK(mutex_stream); + + assert(s); + + //if (verbose) { + MDBGLOG("sound", "INFO\t[%s()]: Stream moved to device %s (%u, %ssuspended).", __func__, pa_stream_get_device_name(s), pa_stream_get_device_index(s), ((pa_stream_is_suspended(s)) ? "" : "INFO\t[%s()]: not ")); + //} + + TC_MUTEX_UNLOCK(mutex_stream); +} + + +/*****************************************************************************/ +/* This is called whenever the context status changes */ +static void APP_CC context_state_callback(pa_context * c, void * userdata) { + assert(c); + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: ",__func__); + } + + switch (pa_context_get_state(c)) { + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; + + case PA_CONTEXT_READY: { + int r = 0; + pa_buffer_attr buffer_attr; + + TC_MUTEX_LOCK(mutex_stream); + + assert(c); + assert(!stream); + + if (verbose) { + MDBGLOG("sound", "INFO\t[%s()]: Connection established.", __func__); + } + + stream_name = g_strdup("xrdp_sink"); + if (!(stream = pa_stream_new(c, stream_name, &sample_spec, ((channel_map_set) ? &channel_map : NULL)))) { + TC_MUTEX_UNLOCK(mutex_stream); + MDBGLOG("sound", "ERROR\t[%s()]: pa_stream_new() failed: %s", __func__, pa_strerror(pa_context_errno(c))); + goto fail; + } + + pa_stream_set_state_callback(stream, stream_state_callback, NULL); + pa_stream_set_read_callback(stream, stream_read_callback, NULL); + pa_stream_set_suspended_callback(stream, stream_suspended_callback, NULL); + pa_stream_set_moved_callback(stream, stream_moved_callback, NULL); + pa_stream_set_underflow_callback(stream, stream_underflow_callback, NULL); + pa_stream_set_overflow_callback(stream, stream_overflow_callback, NULL); + pa_stream_set_started_callback(stream, stream_started_callback, NULL); + pa_stream_set_event_callback(stream, stream_event_callback, NULL); + pa_stream_set_buffer_attr_callback(stream, stream_buffer_attr_callback, NULL); + + g_memset(&buffer_attr, 0, sizeof(buffer_attr)); + buffer_attr.tlength = (uint32_t) -1; + buffer_attr.maxlength = (uint32_t) -1; + buffer_attr.prebuf = (uint32_t) -1; + buffer_attr.minreq = (uint32_t) -1; + buffer_attr.fragsize = (uint32_t) -1; + + buffer_attr.tlength = (uint32_t) 32768; + buffer_attr.maxlength = (uint32_t) -1; + buffer_attr.prebuf = (uint32_t) 0; + buffer_attr.minreq = (uint32_t) -1; + buffer_attr.fragsize = (uint32_t) -1; + + pa_stream_set_latency_update_callback(stream, pa_stream_latency_update_cb, NULL); + + TC_MUTEX_UNLOCK(mutex_stream); + + if (mode == PLAYBACK) { + pa_cvolume cv; + if ((r = pa_stream_connect_playback(stream, device, latency > 0 ? &buffer_attr : NULL, flags | PA_STREAM_START_CORKED, volume_is_set ? pa_cvolume_set(&cv, sample_spec.channels, volume) : NULL, NULL)) < 0) { + TC_MUTEX_UNLOCK(mutex_stream); + MDBGLOG("sound", "ERROR\t[%s()]: pa_stream_connect_playback() failed: %s", __func__, pa_strerror(pa_context_errno(c))); + goto fail; + } + } + else { + if ((r = pa_stream_connect_record(stream, device, latency > 0 ? &buffer_attr : NULL, flags | PA_STREAM_START_CORKED)) < 0) { + TC_MUTEX_UNLOCK(mutex_stream); + MDBGLOG("sound", "ERROR\t[%s()]: pa_stream_connect_record() failed: %s", __func__, pa_strerror(pa_context_errno(c))); + goto fail; + } + } + + /* Subscribe to events */ + { + int success = 0; + pa_operation * o = (pa_operation *)NULL; + if (!(o = pa_context_subscribe(context, PA_SUBSCRIPTION_MASK_SINK_INPUT, pa_context_success_cb, &success))) { + MDBGLOG("source","ERROR\t[%s()]: pa_context_subscribe() failed: %s", __func__, pa_strerror(pa_context_errno(context))); + goto fail; + } + } + + + TC_MUTEX_LOCK(mutex_init); + TC_COND_BROADCAST(cond_init); + TC_MUTEX_UNLOCK(mutex_init); + + break; + } + + case PA_CONTEXT_TERMINATED: + TC_MUTEX_UNLOCK(mutex_stream); + break; + + case PA_CONTEXT_FAILED: + default: + TC_MUTEX_UNLOCK(mutex_stream); + MDBGLOG("sound", "ERROR\t[%s()]: Connection failure: %s", __func__, pa_strerror(pa_context_errno(c))); + break; + } + + return; + + fail:; + pa_quit(1); + return; +} + +static void APP_CC pa_quit(int ret) { + assert(mainloop_api); + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: quitting PulseAudio",__func__); + } + mainloop_api->quit(mainloop_api, ret); +} + +/* Connection draining complete */ +static void APP_CC context_drain_complete(pa_context * c, void * userdata) { + pa_context_disconnect(c); +} + +/* Stream draining complete */ +static void APP_CC stream_drain_complete(pa_stream * s, int success, void * userdata) { + + TC_MUTEX_LOCK(mutex_stream); + + if (!success) { + MDBGLOG("sound", "ERROR\t[%s()]: Failed to drain stream: %s", __func__, pa_strerror(pa_context_errno(context))); + pa_quit(1); + } + + if (verbose) { + MDBGLOG("sound", "INFO\t[%s()]: Playback stream drained.",__func__); + } + + TC_MUTEX_UNLOCK(mutex_stream); + + pa_stream_disconnect(stream); + + TC_MUTEX_LOCK(mutex_stream); + + pa_stream_unref(stream); + stream = NULL; + + TC_MUTEX_UNLOCK(mutex_stream); + + if (!pa_context_drain(context, context_drain_complete, NULL)) { + pa_context_disconnect(context); + } + else { + if (verbose) { + MDBGLOG("sound", "INFO\t[%s()]: Draining connection to server.", __func__); + } + } +} + +/* Start draining */ +static void APP_CC start_drain(void) { + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: ",__func__); + } + + TC_MUTEX_LOCK(mutex_stream); + + if (stream) { + pa_operation * o = (pa_operation *)NULL; + + pa_threaded_mainloop_lock(mt); + + pa_stream_set_write_callback(stream, NULL, NULL); + + if (!(o = pa_stream_drain(stream, stream_drain_complete, NULL))) { + MDBGLOG("sound", "ERROR\t[%s()]: pa_stream_drain() -> \"%s\"", __func__, pa_strerror(pa_context_errno(context))); + pa_threaded_mainloop_unlock(mt); + TC_MUTEX_UNLOCK(mutex_stream); + pa_quit(1); + return; + } + + pa_operation_unref(o); + + pa_threaded_mainloop_unlock(mt); + } + else { + pa_quit(0); + } + + TC_MUTEX_UNLOCK(mutex_stream); +} + +/* Start draining */ +static void APP_CC start_drain_noquit(void) { + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: ",__func__); + } + + TC_MUTEX_LOCK(mutex_stream); + + if (stream) { + pa_operation * o = (pa_operation *)NULL; + + pa_stream_set_write_callback(stream, NULL, NULL); + + if (!(o = pa_stream_drain(stream, NULL, NULL))) { + TC_MUTEX_UNLOCK(mutex_stream); + MDBGLOG("sound", "ERROR\t[%s()]: pa_stream_drain() -> \"%s\"", __func__, pa_strerror(pa_context_errno(context))); + pa_quit(1); + return; + } + + pa_operation_unref(o); + } + + TC_MUTEX_UNLOCK(mutex_stream); +} + +/*****************************************************************************/ +/* Some data may be written to STDOUT */ +static void APP_CC stdout_callback(pa_mainloop_api * a, pa_io_event * e, int fd, pa_io_event_flags_t f, void * userdata) { + int tcnt = 0; + int cum = 0; + int rem = 0; + int lbuf_index = 0; + int lbuf_length = 0; + int lqueued = 0; + int qcnt = 0; + uint8_t * lbuf = (uint8_t *)NULL; + + assert(a == mainloop_api); + assert(e); + assert(stdio_event == e); + + if (mainloop_api != NULL && stdio_event != NULL) { + mainloop_api->io_free(stdio_event); + stdio_event = NULL; + } + + return; + + TC_MUTEX_LOCK(mutex_buffer); + + if (verbose) { + MDBGLOG("sound", "INFO\t[%s()]: called (buffer = %p, buffer_index = %d, buffer_length = %d) [%d]", __func__, buffer, buffer_index, buffer_length, g_gettid()); + } + + if (buffer == NULL) { + TC_MUTEX_LOCK(mutex_event); + mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL); + TC_MUTEX_UNLOCK(mutex_event); + TC_MUTEX_UNLOCK(mutex_buffer); + goto end; + } + + lbuf = (uint8_t *)g_malloc(buffer_length, 1); + g_memcpy(lbuf, buffer, buffer_length); + lbuf_index = buffer_index; + lbuf_length = buffer_length; + + if (lbuf == NULL) { + TC_MUTEX_UNLOCK(mutex_buffer); + goto end; + } + else if (lbuf != NULL) { + pa_xfree(buffer); + buffer = (uint8_t *)NULL; + buffer_length = buffer_index = 0; + } + + TC_MUTEX_UNLOCK(mutex_buffer); + + while (lbuf_length > 0) { + int rv = sound_queue_packet((uint8_t*)(lbuf+lbuf_index), MINVAL(lbuf_length, MAX_PDU_LENGTH - 16)); + rv = (rv < 0) ? 0 : rv; + lbuf_index += rv; + lbuf_length -= rv; + if (rv > 0) { + lqueued++; + } + } + + if (lbuf != NULL) { + g_free(lbuf); + } + + if (lqueued > 0) { + TC_MUTEX_LOCK(mutex_ready); + g_ready_count += lqueued; + g_ready_playbytes += lbuf_length; + g_ready_playtime = (g_ready_playbytes > 0) ? pa_bytes_to_usec(g_ready_playbytes, &sample_spec) / PA_USEC_PER_MSEC : 0; + g_ready_playtime *= 1; + TC_MUTEX_UNLOCK(mutex_ready); + } + + TC_MUTEX_LOCK(mutex_pktq); + qcnt = g_pktq->getCount(g_pktq); + TC_MUTEX_UNLOCK(mutex_pktq); + TC_MUTEX_LOCK(mutex_ready); + if (g_idle > 0 && cond_ready != NULL && qcnt > 0 && g_ready_waiting > 0 && g_ready_count > 0) { + g_ready_triggered = 1; + if (g_ready_waiting > 0) { + TC_COND_BROADCAST(cond_ready); + } + else { + TC_COND_SIGNAL(cond_ready); + } + } + TC_MUTEX_UNLOCK(mutex_ready); + + end:; + if (verbose) { + MDBGLOG("sound", "INFO\t[%s()]: done. [%d]", __func__, g_gettid()); + } +} + + +/*****************************************************************************/ +/* New data on STDIN */ +static void APP_CC stdin_callback(pa_mainloop_api* a, pa_io_event * e, int fd, pa_io_event_flags_t f, void * userdata) { + size_t l, w = 0; + ssize_t r = 0; + + return; + + assert(a == mainloop_api); + assert(e); + assert(stdio_event == e); + + if (verbose) { + MDBGLOG("sound", "INFO\t[%s()]: called", __func__); + } + + TC_MUTEX_LOCK(mutex_buffer); + + if (buffer) { + TC_MUTEX_LOCK(mutex_event); + mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL); + TC_MUTEX_UNLOCK(mutex_event); + TC_MUTEX_UNLOCK(mutex_buffer); + return; + } + + if (!stream || pa_stream_get_state(stream) != PA_STREAM_READY || !(l = w = pa_stream_writable_size(stream))) { + l = 4096; + } + + buffer = pa_xmalloc(l); + + if ((r = g_file_read(fd, buffer, l)) <= 0) { + if (r == 0) { + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: received EOF",__func__); + } + start_drain(); + } + else { + //MDBGLOG("sound","ERROR\t[%s()]: read() failed (\"%s\")",__func__,strerror(errno)); + pa_quit(1); + } + + TC_MUTEX_LOCK(mutex_event); + mainloop_api->io_free(stdio_event); + stdio_event = NULL; + TC_MUTEX_UNLOCK(mutex_event); + return; + } + + buffer_length = (uint32_t) r; + buffer_index = 0; + + TC_MUTEX_UNLOCK(mutex_buffer); + + if (w) { + do_stream_write(w); + } +} + +/*****************************************************************************/ +/* Write some data to the stream */ +static void APP_CC do_stream_write(size_t length) { + size_t l; + assert(length); + + if (verbose) { + MDBGLOG("sound", "INFO\t[%s()]: called", __func__); + } + + TC_MUTEX_LOCK(mutex_buffer); + + if (!buffer || !buffer_length) { + return; + } + + l = length; + if (l > buffer_length) { + l = buffer_length; + } + + if (pa_stream_write(stream, (uint8_t*) buffer + buffer_index, l, NULL, 0, PA_SEEK_RELATIVE) < 0) { + MDBGLOG("sound","ERROR\t[%s()]: pa_stream_write() failed (\"%s\")", __func__, pa_strerror(pa_context_errno(context))); + TC_MUTEX_UNLOCK(mutex_buffer); + pa_quit(1); + return; + } + + buffer_length -= l; + buffer_index += l; + + if (!buffer_length) { + pa_xfree(buffer); + buffer = NULL; + buffer_index = buffer_length = 0; + } + + TC_MUTEX_UNLOCK(mutex_buffer); +} + +/*****************************************************************************/ +static void APP_CC stream_suspended_callback(pa_stream * s, void * userdata) { + + TC_MUTEX_LOCK(mutex_stream); + + assert(s); + + //if (verbose) { + if (pa_stream_is_suspended(s)) { + MDBGLOG("sound", "Stream device suspended.", __func__); + } + else { + MDBGLOG("sound", "Stream device resumed.", __func__); + } + //} + + TC_MUTEX_UNLOCK(mutex_stream); +} + +/*****************************************************************************/ +static void APP_CC stream_underflow_callback(pa_stream * s, void * userdata) { + + TC_MUTEX_LOCK(mutex_stream); + + assert(s); + + //if (verbose) { + MDBGLOG("sound", "INFO\t[%s()]: Stream underrun.", __func__); + //} + + TC_MUTEX_UNLOCK(mutex_stream); +} + +/*****************************************************************************/ +static void APP_CC stream_overflow_callback(pa_stream * s, void * userdata) { + + TC_MUTEX_LOCK(mutex_stream); + + assert(s); + + //if (verbose) { + MDBGLOG("sound", "INFO\t[%s()]: Stream overflow.", __func__); + //} + + TC_MUTEX_UNLOCK(mutex_stream); +} + +/*****************************************************************************/ +static void APP_CC stream_buffer_attr_callback(pa_stream * s, void * userdata) { + + TC_MUTEX_LOCK(mutex_stream); + + assert(s); + + //if (verbose) { + MDBGLOG("sound", "INFO\t[%s()]: Stream buffer attributes changed.", __func__); + //} + + TC_MUTEX_UNLOCK(mutex_stream); +} + +/*****************************************************************************/ + +static void APP_CC stream_write_callback(pa_stream * s, size_t len, void * userdata) { + + TC_MUTEX_LOCK(mutex_stream); + + assert(s); + + //if (verbose) { + MDBGLOG("sound", "INFO\t[%s()]: called", __func__); + //} + + TC_MUTEX_UNLOCK(mutex_stream); +} + +/*****************************************************************************/ +static void * APP_CC +sound_timer_loop(void * arg) { + void * rv = (void *)NULL; + unsigned char l_ok = 1; + unsigned char done = 0; + + TC_BARR_WAIT(barr_formats); + + if (g_client_formats_received == 0 || g_client_format_index == 0) { + l_ok = 0; + TC_MUTEX_LOCK(mutex_formats); + if (g_client_formats_received == 0 || g_client_format_index == 0) { + TC_MUTEX_UNLOCK(mutex_formats); + g_sleep(3000); + TC_MUTEX_LOCK(mutex_sound); + TC_MUTEX_LOCK(mutex_formats); + if (g_client_format_index < 0) { + TC_MUTEX_UNLOCK(mutex_formats); + TC_MUTEX_LOCK(mutex_close); + g_received_close_pdu = 1; + TC_MUTEX_UNLOCK(mutex_close); + sound_deinit(); + } + else { + TC_MUTEX_UNLOCK(mutex_formats); + l_ok = 1; + } + TC_MUTEX_UNLOCK(mutex_sound); + } + else { + TC_MUTEX_UNLOCK(mutex_formats); + l_ok = 1; + } + } + if (l_ok > 0) { + TC_MUTEX_LOCK(mutex_pa); + if (g_pa_ready < 1) { + g_pa_ready = 1; + } + if (cond_pa != NULL) { + TC_COND_BROADCAST(cond_pa); + } + TC_MUTEX_UNLOCK(mutex_pa); + } + + TC_THREAD_EXIT(NULL); + return rv; +} + + +/*****************************************************************************/ +static void APP_CC pa_sink_info_cb(struct pa_context * c, const pa_sink_info * i, int is_last, void * userdata) { + assert(c); + MDBGLOG("sound","INFO\t[%s()]: called (c = %p, i = %p, userdata = %p)",__func__,c,i,userdata); + if (i == NULL) { + goto end; + } + else { + TC_MUTEX_LOCK(mutex_sink); + g_sink_index = i->index; + TC_MUTEX_UNLOCK(mutex_sink); + pa_sink_state_callback(c, i, userdata); + //pa_sink_input_info_cb(); + } + end:; + pa_threaded_mainloop_signal(mt, 0); + return; +} + +/*****************************************************************************/ +static void APP_CC pa_source_info_cb(struct pa_context * c, const pa_source_info * i, int is_last, void * userdata) { + assert(c); + MDBGLOG("sound","INFO\t[%s()]: called (c = %p, i = %p, userdata = %p)",__func__,c,i,userdata); + if (i == NULL) { + goto end; + } + else { + TC_MUTEX_LOCK(mutex_sink); + //g_source_index = i->index; + TC_MUTEX_UNLOCK(mutex_sink); + pa_source_state_callback(c, i, userdata); + //pa_source_input_info_cb(); + } + end:; + if (1) { + pa_threaded_mainloop_signal(mt, 0); + } + return; +} + +/*****************************************************************************/ +static void APP_CC pa_subscribe_cb(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void * userdata) { + unsigned char tlock = 0; + pa_operation * o = (pa_operation *)NULL; + + assert(c); + + if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: called (index = %d)",__func__,index); + } + + if (!pa_threaded_mainloop_in_thread(mt)) { + pa_threaded_mainloop_lock(mt); + tlock = 1; + } + TC_MUTEX_LOCK(mutex_stream); + if (!stream || + index != pa_stream_get_index(stream) || + (t != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE) && + t != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW))) { + } + if (stream != NULL) { + index != pa_stream_get_index(stream); + } + MDBGLOG("sound","INFO\t[%s()]: index = %d",__func__,index); + //if (!(o = pa_context_get_sink_info_by_index(c, index, &pa_sink_info_cb, NULL))) { + if (!(o = pa_context_get_source_info_by_index(c, index, &pa_source_info_cb, NULL))) { + pa_threaded_mainloop_unlock(mt); + TC_MUTEX_UNLOCK(mutex_stream); + MDBGLOG("ERROR\t[%s()]: pa_context_get_sink_info() failed (\"%s\")", __func__, pa_strerror(pa_context_errno(c))); + goto end; + } + else { + TC_MUTEX_UNLOCK(mutex_stream); + if (tlock) { + pa_threaded_mainloop_wait(mt); + pa_operation_unref(o); + pa_threaded_mainloop_unlock(mt); + } + else { + pa_operation_unref(o); + } + } + + end:; + if (tlock) { + MDBGLOG("sound","INFO\t[%s()]: (tlock = %d)",__func__,index,tlock); + pa_threaded_mainloop_unlock(mt); + } + return; +} + +static void APP_CC pa_context_success_cb(pa_context * c, int success, void * userdata) { + assert(c); + MDBGLOG("sound","INFO\t[%s()]: called",__func__); +} + +static void APP_CC pa_stream_latency_update_cb(pa_stream *s, void *userdata) { + assert(s); + MDBGLOG("sound","INFO\t[%s()]: called",__func__); + //pa_threaded_mainloop_signal(mainloop, 0); +} + +static int APP_CC sound_get_pulseaudio_server(const char ** server) { + int rv = 0; + glob_t tglob; + char globdir[164]; + g_memset(globdir, 0, sizeof(globdir)); + if (server == NULL) { + rv = -1; + goto end; + } + else { + *server = g_getenv("PULSE_SERVER"); + } + if (*server == NULL) { + uid_t tuid = 0; + unsigned int idx = 0; + g_memset(&tglob,0,sizeof(glob_t)); + pa_get_home_dir(globdir, sizeof(globdir) - 48); + g_strncat(globdir, "/.pulse/*-runtime/native", sizeof(globdir)); + glob(globdir,GLOB_NOSORT,NULL,&tglob); + for (idx = 0; idx < tglob.gl_pathc; idx++) { + int fd = -1; + struct stat finfo; + g_memset(&finfo,0,sizeof(struct stat)); + if (g_strlen(tglob.gl_pathv[idx]) > 0 && stat(tglob.gl_pathv[idx], &finfo) == 0) { + if (S_ISSOCK(finfo.st_mode)) { + *server = g_strndup(tglob.gl_pathv[idx], 164); + break; + } + } + else { + continue; + } + } + globfree(&tglob); + } + + end:; + MDBGLOG("sound","DEBUG\t[%s()]: *server = \"%s\"",__func__,*server); + return rv; +} + +/* UNIX signal to quit recieved */ +static void APP_CC pa_exit_signal_callback(pa_mainloop_api * m, pa_signal_event * e, int sig, void * userdata) { + //if (verbose) { + MDBGLOG("sound","INFO\t[%s()]: received exit signal",__func__); + //} + pa_quit(0); +} + +static void APP_CC pa_sink_input_info_cb(pa_context * c, const pa_sink_input_info * i, int eol, void * userdata) { + MDBGLOG("sound","INFO\t[%s()]: called (eol = %d)",__func__,eol); + TC_MUTEX_LOCK(mutex_sink); + if (i != NULL && i->sink == g_sink_index) { + g_sink_input_count++; + } + if (eol > 0 && g_sink_query_waiting > 0) { + if (g_sink_query_waiting > 1) { + TC_COND_BROADCAST(cond_sink); + } + else { + TC_COND_SIGNAL(cond_sink); + } + } + TC_MUTEX_UNLOCK(mutex_sink); + return; +} + diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/config.c posixrdp/posixxrdp.orig/sesman/config.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/config.c 2010-11-02 11:51:10.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/config.c 2010-11-08 09:56:45.000000000 +0100 @@ -179,13 +179,13 @@ } /* showing read config */ - /* g_printf("sesman config:\r\n"); + g_printf("sesman config:\r\n"); g_printf("\tListenAddress: %s\r\n", cf->listen_address); g_printf("\tListenPort: %s\r\n", cf->listen_port); g_printf("\tEnableUserWindowManager: %i\r\n", cf->enable_user_wm); g_printf("\tUserWindowManager: %s\r\n", cf->user_wm); g_printf("\tDefaultWindowManager: %s\r\n", cf->default_wm); - g_printf("\tAuthFilePath: %s\r\n", ((cf->auth_file_path) ? (cf->auth_file_path) : ("disabled"))); */ + g_printf("\tAuthFilePath: %s\r\n", ((cf->auth_file_path) ? (cf->auth_file_path) : ("disabled"))); return 0; } @@ -236,11 +236,11 @@ lc->log_file=g_strdup("./sesman.log"); } - /* g_printf("logging configuration:\r\n"); + g_printf("logging configuration:\r\n"); g_printf("\tLogFile: %s\r\n",lc->log_file); g_printf("\tLogLevel: %i\r\n", lc->log_level); g_printf("\tEnableSyslog: %i\r\n", lc->enable_syslog); - g_printf("\tSyslogLevel: %i\r\n", lc->syslog_level); */ + g_printf("\tSyslogLevel: %i\r\n", lc->syslog_level); return 0; } @@ -295,7 +295,7 @@ } /* printing security config */ - /* g_printf("security configuration:\r\n"); + g_printf("security configuration:\r\n"); g_printf("\tAllowRootLogin: %i\r\n",sc->allow_root); g_printf("\tMaxLoginRetry: %i\r\n",sc->login_retry); if (sc->ts_users_enable) @@ -313,7 +313,7 @@ else { g_printf("\tNo TSAdminsGroup defined\r\n"); - } */ + } return 0; } @@ -358,11 +358,11 @@ } /* printing security config */ - /* g_printf("session configuration:\r\n"); + g_printf("session configuration:\r\n"); g_printf("\tMaxSessions: %i\r\n", se->max_sessions); g_printf("\tKillDisconnected: %i\r\n", se->kill_disconnected); g_printf("\tIdleTimeLimit: %i\r\n", se->max_idle_time); - g_printf("\tDisconnectedTimeLimit: %i\r\n", se->max_idle_time); */ + g_printf("\tDisconnectedTimeLimit: %i\r\n", se->max_idle_time); return 0; } @@ -386,11 +386,11 @@ } /* printing security config */ - /* g_printf("X11rdp parameters:\r\n"); + g_printf("X11rdp parameters:\r\n"); for (i = 0; i < cs->rdp_params->count; i++) { g_printf("\tParameter %02d %s\r\n", i, (char*)list_get_item(cs->rdp_params, i)); - } */ + } return 0; } @@ -414,11 +414,11 @@ } /* printing security config */ - /* g_printf("Xvnc parameters:\r\n"); + g_printf("Xvnc parameters:\r\n"); for (i = 0; i < cs->vnc_params->count; i++) { g_printf("\tParameter %02d %s\r\n", i, (char*)list_get_item(cs->vnc_params, i)); - } */ + } return 0; } diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/dynamic/Makefile.am posixrdp/posixxrdp.orig/sesman/dynamic/Makefile.am --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/dynamic/Makefile.am 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/dynamic/Makefile.am 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,40 @@ + +AM_CFLAGS = \ + -pthread \ + -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ + -DXRDP_SBIN_PATH=\"${sbindir}\" \ + -DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \ + -DXRDP_PID_PATH=\"${localstatedir}/run\" \ + -D_FILE_OFFSET_BITS=64 \ + -D_REENTRANT \ + -D_GNU_SOURCE \ + -D_XOPEN_SOURCE_EXTENDED \ + -D_POSIX_PTHREAD_SEMATICS \ + -D_POSIX_PTHREADS + + +LDFLAGS = \ + -lpthread + +INCLUDES = \ + -I$(top_srcdir)/common + +LDADD = \ + $(top_builddir)/common/libcommon.la + +sbin_PROGRAMS = \ + xrdp_drdynvc_interface \ + xrdp_rdpeai + +xrdp_drdynvc_interface_SOURCES = \ + xrdp_drdynvc_interface.c \ + xrdp_drdynvc_interface.h + +xrdp_rdpeai_SOURCES = \ + xrdp_rdpeai.c \ + xrdp_rdpeai.h + +xrdp_rdpeai_LDFLAGS = \ + -lpulse \ + -lpulse-simple \ + -lgsm diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/dynamic/xrdp_drdynvc_interface.c posixrdp/posixxrdp.orig/sesman/dynamic/xrdp_drdynvc_interface.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/dynamic/xrdp_drdynvc_interface.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/dynamic/xrdp_drdynvc_interface.c 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,958 @@ + +#include "xrdp_drdynvc_interface.h" + +static const char sockpath[] = "/tmp/.audio_input_socket"; +static const char intsockname[] = "audio_interface_socket"; +static const char inpipepath[] = "/tmp/audio_input_inpipe"; +static const char outpipepath[] = "/tmp/audio_input_outpipe"; + +static char * g_laddr = (char *)NULL; +static char * g_lport = (char *)NULL; + +static volatile unsigned char g_done = 0; +static int g_interface_type = WO_LOCAL; + +static stream_list_t * ilist = (stream_list_t *)NULL; +static stream_list_t * olist = (stream_list_t *)NULL; +static stream_list_t * dlist = (stream_list_t *)NULL; +static volatile int ilist_count = 0; +static volatile int olist_count = 0; +static volatile int dlist_count = 0; + +static struct stream * g_ins = (struct stream *)NULL; +static tbus g_sck = -1; +static int g_uniqid = 0; +static volatile tbus g_channel_id = -1; + +static const unsigned int g_trans_socket_type = WO_LOCAL; +static struct trans * g_trans = (struct trans *)NULL; + +static tc_t g_thread_barr; +static tc_p barr_thread = &g_thread_barr; +static tc_t g_loop_barr; +static tc_p barr_loop = &g_loop_barr; + +static tc_t g_recv_thread; +static tc_p thread_recv = &g_recv_thread; +static tc_t g_send_thread; +static tc_p thread_send = &g_send_thread; + +static tc_t g_inpipe_thread; +static tc_p thread_inpipe = &g_inpipe_thread; +static tc_t g_outpipe_thread; +static tc_p thread_outpipe = &g_outpipe_thread; + +static tc_t g_ins_mutex = TC_MUTEX_INITIALIZER; +static tc_p mutex_ins = &g_ins_mutex; +static tc_t g_ilist_mutex = TC_MUTEX_INITIALIZER; +static tc_p mutex_ilist = &g_ilist_mutex; +static tc_t g_olist_mutex = TC_MUTEX_INITIALIZER; +static tc_p mutex_olist = &g_olist_mutex; +static tc_t g_dlist_mutex = TC_MUTEX_INITIALIZER; +static tc_p mutex_dlist = &g_dlist_mutex; +static tc_t g_done_mutex = TC_MUTEX_INITIALIZER; +static tc_p mutex_done = &g_done_mutex; +static tc_t g_sck_mutex = TC_MUTEX_INITIALIZER; +static tc_p mutex_sck = &g_sck_mutex; +static tc_t g_say_mutex = TC_MUTEX_INITIALIZER; +static tc_p mutex_say = &g_say_mutex; +static tc_t g_id_mutex = TC_MUTEX_INITIALIZER; +static tc_p mutex_id = &g_id_mutex; + +static tc_t g_ilist_cond = TC_COND_INITIALIZER; +static tc_p cond_ilist = &g_ilist_cond; +static tc_t g_olist_cond = TC_COND_INITIALIZER; +static tc_p cond_olist = &g_olist_cond; +static tc_t g_dlist_cond = TC_COND_INITIALIZER; +static tc_p cond_dlist = &g_dlist_cond; +static tc_t g_sck_cond = TC_COND_INITIALIZER; +static tc_p cond_sck = &g_sck_cond; + +static tc_t g_pending_mutex = TC_MUTEX_INITIALIZER; +static tc_p mutex_pending = &g_pending_mutex; +static tc_t g_pending_cond = TC_COND_INITIALIZER; +static tc_p cond_pending = &g_pending_cond; + +static DYNVC_ANY g_pdu; +static volatile unsigned char g_pending = 0; +static volatile unsigned int g_pending_waiting = 0; +static volatile unsigned int g_ilist_waiting = 0; +static volatile unsigned int g_ilist_triggered = 0; +static volatile unsigned int g_olist_waiting = 0; +static volatile unsigned int g_olist_triggered = 0; +static volatile unsigned int g_dlist_waiting = 0; +static volatile unsigned int g_dlist_triggered = 0; + +int APP_CC main(int, char * []); +static int APP_CC init_locks(void); +static int APP_CC launch_threads(void); +static void * APP_CC recv_loop(void *); +static void * APP_CC send_loop(void *); +static void * APP_CC inpipe_loop(void *); +static void * APP_CC outpipe_loop(void *); +static int APP_CC handle_create(const char *, uint32_t); +static int APP_CC handle_close(uint32_t); +static int APP_CC handle_data(int, tbus); +static int APP_CC get_connection(tbus *, const char *, const char *); +static size_t APP_CC inpipe_data_in(struct trans *); + +static int dynamic_channel_id = -1; + +#define NUM_THREADS 5 + +int APP_CC main(int argc, char * argv[]) { + int rv = 0; + tbus sck = -1; + char * caddr = (char *)NULL; + char * cport = "7712"; + char * laddr = (char *)NULL; + char * lport = "7714"; + unsigned char done = 0; + + g_memset(&g_pdu, 0, sizeof(DYNVC_ANY)); + + make_stream(g_ins); + init_stream(g_ins, MAX_STREAM); + + if (argc > 1 && argv[1] != NULL && g_strlen(argv[1]) > 0) { + char * cpos = (char *)NULL; + cpos = g_strchr(argv[1],':'); + if (cpos == NULL) { + caddr = g_strndup(argv[1],64); + } + else { + cport = g_strndup(cpos,10); + caddr = g_strndup(argv[1],(cpos - argv[1])); + } + if (argc > 2 && argv[2] != NULL && g_strlen(argv[2]) > 0) { + laddr = g_strndup(argv[2],64);; + lport = (char *)NULL; + g_laddr = laddr; + g_lport = lport; + } + } + + init_locks(); + launch_threads(); + + TC_MUTEX_LOCK(mutex_sck); + if ((rv = get_connection(&sck, caddr, cport)) == 0) { + g_sck = sck; + } + else { + SAY("failed to establish connection (rv = %d, sck = %d)", rv, sck); + rv = -1; + TC_MUTEX_LOCK(mutex_done); + g_done = 1; + TC_MUTEX_UNLOCK(mutex_done); + g_sck = -1; + TC_MUTEX_UNLOCK(mutex_sck); + goto end; + } + TC_MUTEX_UNLOCK(mutex_sck); + TC_BARR_WAIT(barr_thread); + TC_BARR_WAIT(barr_loop); + + handle_create("AUDIO_INPUT", 0); + + TC_MUTEX_LOCK(mutex_done); + done = g_done; + TC_MUTEX_UNLOCK(mutex_done); + while (!done) { + if (g_pending == 0) { + TC_MUTEX_LOCK(mutex_pending); + g_pending_waiting++; + if (g_pending == 0) { + TC_COND_WAIT(cond_pending, mutex_pending); + } + g_pending_waiting--; + TC_MUTEX_UNLOCK(mutex_pending); + } + if (g_done == 0) { + char * cmd = (char *)NULL; + tbus tstdin = -1; + tstdin = STDIN_FILENO; + tbus ifd = -1; + if (!g_strcmp(cmd,"data")) { + int cnum = 0; + if (argc > 3 && argv[3] != NULL && g_strlen(argv[3]) > 0) { + cnum = g_atoi(argv[3]); + } + if (argc > 4 && argv[4] != NULL && g_strlen(argv[4]) > 0) { + ifd = g_file_open(argv[4]); + if (ifd < 1) { + SAY("failed to open \"%s\"",argv[4]); + } + } + else { + ifd = (tbus)tstdin; + } + if (ifd > -1) { + handle_data(cnum, (const tbus)ifd); + } + } + else if (!g_strcmp(cmd,"close")) { + int cnum = 0; + if (argc > 3 && argv[3] != NULL && g_strlen(argv[3]) > 0) { + cnum = g_atoi(argv[3]); + } + handle_close(cnum); + } + } + TC_MUTEX_LOCK(mutex_done); + done = g_done; + TC_MUTEX_UNLOCK(mutex_done); + } + + TC_THREAD_JOIN(thread_recv->thread, NULL); + TC_THREAD_JOIN(thread_send->thread, NULL); + TC_THREAD_JOIN(thread_inpipe->thread, NULL); + TC_THREAD_JOIN(thread_outpipe->thread, NULL); + + if (g_sck > -1) { + close(g_sck); + g_sck = -1; + } + + end:; + g_sleep(200); + return rv; +} + +static int APP_CC init_locks() { + int rv = 0; + tc_t mattr; + tc_p pmattr = &mattr; + tc_t cattr; + tc_p pcattr = &cattr; + + g_memset(pmattr, 0, sizeof(tc_t)); + g_memset(pcattr, 0, sizeof(tc_t)); + + TC_MUTATTR_INIT(pmattr); + TC_MUTEX_INIT(mutex_ins, pmattr); + TC_MUTEX_INIT(mutex_ilist, pmattr); + TC_MUTEX_INIT(mutex_olist, pmattr); + TC_MUTEX_INIT(mutex_dlist, pmattr); + TC_MUTEX_INIT(mutex_done, pmattr); + TC_MUTEX_INIT(mutex_sck, pmattr); + TC_MUTEX_INIT(mutex_pending, pmattr); + TC_MUTEX_INIT(mutex_say, pmattr); + + TC_CONDATTR_INIT(pcattr); + TC_COND_CREATE(cond_ilist, pcattr); + TC_COND_CREATE(cond_olist, pcattr); + TC_COND_CREATE(cond_dlist, pcattr); + TC_COND_CREATE(cond_sck, pcattr); + TC_COND_CREATE(cond_pending, pcattr); + + TC_BARR_INIT(barr_thread, NUM_THREADS); + TC_BARR_INIT(barr_loop, NUM_THREADS); + + return rv; +} + +static int APP_CC launch_threads() { + int rv = 0; + tc_t attr; + tc_p pattr = &attr; + + g_memset(pattr, 0, sizeof(tc_t)); + TC_THREADATTR_INIT(pattr); + TC_THREADATTR_SETDETACHSTATE(pattr, TC_CREATE_JOINABLE); + + TC_THREAD_INIT_FULL(&(thread_recv->thread), &(pattr->threadattr), &recv_loop, NULL); + TC_THREAD_INIT_FULL(&(thread_send->thread), &(pattr->threadattr), &send_loop, NULL); + + TC_THREAD_INIT_FULL(&(thread_inpipe->thread), &(pattr->threadattr), &inpipe_loop, g_laddr); + TC_THREAD_INIT_FULL(&(thread_outpipe->thread), &(pattr->threadattr), &outpipe_loop, NULL); + + return rv; +} + +static void * APP_CC send_loop(void * arg) { + void * rv = (void *)NULL; + unsigned char done = 0; + unsigned char past_barrier = 0; + unsigned char loop_done = 0; + TC_BARR_WAIT(barr_thread); + TC_MUTEX_LOCK(mutex_done); + done = g_done; + TC_MUTEX_UNLOCK(mutex_done); + while (!done) { + unsigned char cont = 0; + stream_list_t lentry; // = (stream_list_t *)NULL; + stream_list_t * entry = &lentry; + struct stream * s = (struct stream *)NULL; + int cnt = 0; + TC_MUTEX_LOCK(mutex_olist); + if (!loop_done) { + TC_BARR_WAIT(barr_loop); + loop_done = 1; + } + if (olist_count < 1) { + g_olist_waiting++; + TC_COND_WAIT(cond_olist, mutex_olist); + g_olist_waiting--; + if (g_olist_triggered < 1) { + cont = 1; + } + g_olist_triggered = 0; + } + TC_MUTEX_UNLOCK(mutex_olist); + if (cont > 0) { + continue; + } + TC_MUTEX_LOCK(mutex_olist); + entry = NULL; + if (olist_count > 0) { + SQ_DEQ(olist, &entry); + olist_count--; + } + if (entry == NULL) { + TC_MUTEX_UNLOCK(mutex_olist); + SAY("deq'd entry is NULL"); + } + else { + size_t len = 0; + TC_MUTEX_UNLOCK(mutex_olist); + s = entry->s; + len = (s == NULL || s->data == NULL || s->p == NULL || s->end == NULL || s->p < s->data || s->end <= s->p || s->size < 1 || (s->end - s->data) > s->size || (s->end - s->p) > s->size) ? 0 : (s->end - s->data); + if (len < 1) { + SAY("len is zero (s = %p, s->p = %p, s->end = %p, s->data = %p, s->size = %d)",s,s->p,s->end,s->data,s->size); + } + else { + if (g_sck > -1 && g_tcp_socket_ok(g_sck) && g_tcp_can_send(g_sck, 50)) { + size_t rlen = 0; + rlen = g_tcp_send_force(g_sck, s->p, len, 0); + } + else { + SAY("unable to send on socket %d",g_sck); + } + } + } + TC_MUTEX_LOCK(mutex_done); + done = g_done; + TC_MUTEX_UNLOCK(mutex_done); + } + TC_THREAD_EXIT(NULL); + return rv; +} + +static void * APP_CC recv_loop(void * arg) { + void * rv = (void *)NULL; + unsigned char done = 0; + unsigned char past_barrier = 0; + unsigned char got_ok = 0; + tbus fd = -1; + + TC_BARR_WAIT(barr_thread); + fd = g_sck; + + if (fd < 1) { + SAY("invalid wait object"); + } + else { + tbus sck = -1; + TC_MUTEX_LOCK(mutex_done); + done = g_done; + TC_MUTEX_UNLOCK(mutex_done); + TC_BARR_WAIT(barr_loop); + while (!done) { + unsigned char is_ok = 0; + if (g_obj_wait(&fd, 1, NULL, 0, 0) < 0) { + } + else if (g_is_wait_obj_set(fd)) { + unsigned char empty = 0; + unsigned char buf[MAX_STREAM]; + size_t blen = 0; + struct stream * s = (struct stream *)NULL; + g_memset(buf,0,sizeof(buf)); + while (g_done == 0 && g_tcp_can_recv(fd, 50) && (blen = g_tcp_recv(fd, buf, 4096, 0)) > 0) { + struct stream * s = (struct stream *)NULL; + stream_list_t * entry = (stream_list_t *)NULL; + if (g_channel_id < 0 && blen > 3 && buf[0] == 'O' && buf[1] == 'K' && buf[2] == '\n') { + char nbuf[7] = {0,0,0,0,0,0,0}; + char c = 0; + ptrdiff_t i = 3; + c = buf[i]; + while ((i - 3) < blen && i < 9 && (c >= '0' && c <= '9')) { + nbuf[(i - 3)] = c; + i++; + c = buf[i]; + } + if (g_strlen(nbuf) > 0) { + TC_MUTEX_LOCK(mutex_id); + g_channel_id = g_atoi(nbuf); + TC_MUTEX_UNLOCK(mutex_id); + is_ok = 1; + } + } + if (!is_ok) { + blen = MIN(blen, sizeof(buf)); + if (blen > 0) { + make_stream(s); + init_stream(s, sizeof(buf)); + entry = (stream_list_t *)g_malloc(sizeof(stream_list_t), 1); + out_uint8a(s, buf, blen); + s_mark_end(s); + s->p = s->data; + entry->s = s; + TC_MUTEX_LOCK(mutex_ilist); + SQ_ENQ(ilist, entry); + ilist_count++; + SAY("enq'd entry (%p; blen = %d)",entry,blen); + if (g_ilist_waiting > 0) { + g_ilist_triggered = 1; + if (g_ilist_waiting > 1) { + TC_COND_BROADCAST(cond_ilist); + } + else { + TC_COND_SIGNAL(cond_ilist); + } + } + TC_MUTEX_UNLOCK(mutex_ilist); + } + } + g_memset(buf,0,sizeof(buf)); + } + } + if (g_done > 0) { + TC_MUTEX_LOCK(mutex_done); + done = g_done; + TC_MUTEX_UNLOCK(mutex_done); + } + } + } + + end:; + SAY("done"); + TC_THREAD_EXIT(NULL); + return rv; +} + +static int APP_CC get_connection(tbus * fd, const char * iaddress, const char * iport) { + int rv = 0; + tbus sck = -1; + char * addr = "localhost"; + char * port = "7712"; + + if (fd == NULL) { + SAY("NULL input"); + rv = -1; + } + else { + unsigned char is_local = 0; + if (iaddress != NULL && g_strlen(iaddress) > 0) { + addr = (char *)iaddress; + } + if (iport != NULL && g_strlen(iport) > 0) { + port = (char *)iport; + } + if (addr != NULL && g_strlen(addr) > 0 && g_strchr(addr, '/') != NULL) { + is_local = 1; + } + else { + is_local = 0; + } + if (is_local) { + SAY("(using local socket)"); + if ((sck = g_tcp_local_socket()) < 1) { + rv = -2; + } + else { + rv = g_tcp_local_connect(sck, addr); + } + } + else { + if ((sck = g_tcp_socket()) < 1) { + rv = -2; + } + else { + rv = g_tcp_connect(sck, addr, port); + } + } + *fd = sck; + } + + return rv; +} + +static int APP_CC handle_create(const char * cname, uint32_t cnum) { + int rv = 0; + DYNVC_CREATE_REQ * pdu = (DYNVC_CREATE_REQ *)(&(g_pdu.create_req)); + const uint32_t magic = RDP_PACKET_MAGIC; + uint32_t cmd = RDPCHAN_OPEN; + uint32_t size = 0; + uint32_t chanid = cnum; + uint32_t uniqid = 0; + uint32_t crc32 = 0; + struct stream * s = (struct stream *)NULL; + stream_list_t * entry = (stream_list_t *)NULL; + char * p = (char *)NULL; + uint32_t * p_crc32 = (uint32_t *)NULL; + + make_stream(s); + init_stream(s, MAX_STREAM); + entry = (stream_list_t *)g_malloc(sizeof(stream_list_t), 1); + construct_DYNVC_CREATE_REQ(pdu); + g_snprintf(pdu->ChannelName,48,cname); + size = g_strlen(pdu->ChannelName); + uniqid = g_uniqid++; + out_uint32_le(s, magic); + out_uint32_le(s, cmd); + out_uint32_le(s, size); + out_uint32_le(s, chanid); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)(s->p); + out_uint32_le(s, crc32); + p = s->p; + out_uint8a(s, pdu->ChannelName, g_strlen(pdu->ChannelName)); + s_mark_end(s); + *p_crc32 = Crc32_ComputeBuf(0, p, (s->end - p) - 1); + s->p = s->data; + entry->s = s; + TC_MUTEX_LOCK(mutex_olist); + SQ_ENQ(olist, entry); + olist_count++; + TC_MUTEX_UNLOCK(mutex_olist); + TC_MUTEX_LOCK(mutex_olist); + if (g_olist_waiting > 0) { + g_olist_triggered = 1; + if (g_olist_waiting > 1) { + TC_COND_BROADCAST(cond_olist); + } + else { + TC_COND_SIGNAL(cond_olist); + } + } + TC_MUTEX_UNLOCK(mutex_olist); + + return rv; +} + +static int APP_CC handle_close(uint32_t cnum) { + int rv = 0; + DYNVC_CLOSE * pdu = (DYNVC_CLOSE *)(&(g_pdu.close)); + const uint32_t magic = RDP_PACKET_MAGIC; + uint32_t cmd = RDPCHAN_CLOSE; + uint32_t size = 0; + uint32_t chanid = cnum; + uint32_t uniqid = 0; + uint32_t crc32 = 0; + struct stream * s = (struct stream *)NULL; + stream_list_t * entry = (stream_list_t *)NULL; + char * p = (char *)NULL; + uint32_t * p_crc32 = (uint32_t *)NULL; + + make_stream(s); + init_stream(s, MAX_STREAM); + entry = (stream_list_t *)g_malloc(sizeof(stream_list_t), 1); + construct_DYNVC_CLOSE(pdu); + pdu->ChannelId = 1; + uniqid = g_uniqid++; + out_uint32_le(s, magic); + out_uint32_le(s, cmd); + out_uint32_le(s, size); + out_uint32_le(s, chanid); + out_uint32_le(s, uniqid); + out_uint32_le(s, crc32); + s_mark_end(s); + s->p = s->data; + entry->s = s; + TC_MUTEX_LOCK(mutex_olist); + SQ_ENQ(olist, entry); + olist_count++; + TC_MUTEX_UNLOCK(mutex_olist); + TC_MUTEX_LOCK(mutex_olist); + if (g_olist_waiting > 0) { + g_olist_triggered = 1; + TC_COND_SIGNAL(cond_olist); + } + TC_MUTEX_UNLOCK(mutex_olist); + TC_MUTEX_LOCK(mutex_ilist); + if (g_ilist_waiting > 0) { + g_ilist_triggered = 1; + TC_COND_SIGNAL(cond_ilist); + } + TC_MUTEX_UNLOCK(mutex_ilist); + + return rv; +} + +static int APP_CC handle_data(int cnum, tbus fd) { + int rv = 0; + DYNVC_DATA_FIRST * first = (DYNVC_DATA_FIRST *)(&(g_pdu.datafirst)); + DYNVC_DATA * pdu = (DYNVC_DATA *)(&(g_pdu.data)); + const uint32_t magic = RDP_PACKET_MAGIC; + uint32_t cmd = RDPCHAN_OPEN; + uint32_t size = 0; + uint32_t chanid = cnum; + uint32_t uniqid = 0; + uint32_t crc32 = 0; + struct stream * s = (struct stream *)NULL; + stream_list_t * entry = (stream_list_t *)NULL; + uint32_t * p_crc32 = (uint32_t *)NULL; + char * p = (char *)NULL; + uint8_t buf[4096]; + unsigned char done = 0; + unsigned int cnt = 0; + size_t len = 0; + size_t total = 0; + const size_t dflen = 1 + 1 + 1 + 4 + 4; + const size_t dlen = 1 + 1 + 1 + 4; + const size_t max_pdu = 1600; + const size_t dfmax = max_pdu - dflen; + const size_t dmax = max_pdu - dlen; + + while (!done) { + g_memset(buf,0,sizeof(buf)); + if (g_trans_socket_type == WO_FIFO || g_trans_socket_type == 0) { + len = g_file_read(fd, buf, dfmax); + } + else if (g_trans_socket_type == WO_LOCAL || g_trans_socket_type == WO_INET) { + len = g_tcp_recv(fd, buf, dmax, 0); + } + total += len; + if (len < dmax) { + done = 1; + } + while (len > 0) { + size_t ulen = 0; + if (cnt == 0 && len >= dmax) { + cmd = RDPCHAN_DATAFIRST; + } + else { + cmd = RDPCHAN_DATA; + } + make_stream(s); + init_stream(s, MAX_STREAM); + entry = (stream_list_t *)g_malloc(sizeof(stream_list_t), 1); + uniqid = g_uniqid++; + ulen = len; + if (cmd == RDPCHAN_DATAFIRST) { + ulen += 4; + } + size = MIN(ulen, ((cmd == RDPCHAN_DATAFIRST) ? dfmax : dmax)); + out_uint32_le(s, magic); + out_uint32_le(s, cmd); + out_uint32_le(s, size); + out_uint32_le(s, chanid); + out_uint32_le(s, uniqid); + p_crc32 = (uint32_t *)(s->p); + out_uint32_le(s, crc32); + if (cmd == RDPCHAN_DATAFIRST) { + out_uint32_le(s, len); + } + p = s->p; + if (len > 0 && buf != NULL) { + out_uint8a(s, buf, len); + } + s_mark_end(s); + if (s->end > p && (s->end - p) > 1) { + *p_crc32 = Crc32_ComputeBuf(0, p, (s->end - p) - 1); + } + s->p = s->data; + entry->s = s; + TC_MUTEX_LOCK(mutex_olist); + SQ_ENQ(olist, entry); + olist_count++; + TC_MUTEX_UNLOCK(mutex_olist); + TC_MUTEX_LOCK(mutex_olist); + if (g_olist_waiting > 0) { + g_olist_triggered = 1; + TC_COND_SIGNAL(cond_olist); + } + TC_MUTEX_UNLOCK(mutex_olist); + len -= size; + s = (struct stream *)NULL; + cnt++; + } + } + + return rv; +} + +static void * APP_CC inpipe_loop(void * arg) { + void * rv = (void *)NULL; + unsigned char done = 0; + unsigned char locked = 0; + unsigned char ready = 0; + tbus fd = -1; + tbus ** objs = (tbus **)NULL; + int tres = 0; + int lres = 0; + char * tpath = (char *)NULL; + + if (g_interface_type == WO_FIFO || g_interface_type == 0) { + if (!g_file_exist(inpipepath)) { + g_create_fifo(inpipepath); + } + fd = g_fifo_open(inpipepath); + fd = g_create_wait_obj_from_fifo(fd, 0); + } + else if (g_interface_type == WO_LOCAL) { + char spath[64] = ""; + char * path = spath; + if (arg != NULL && g_strlen(arg) > 0) { + path = arg; + } + else if (intsockname != NULL && g_strlen(intsockname) > 0) { + g_snprintf(spath, sizeof(spath), "/tmp/%s", intsockname); + path = spath; + } + if (g_file_exist(path)) { + g_file_delete(path); + } + if (path != NULL && g_strlen(path) > 0) { + tpath = g_strdup(path); + } + } + else if (g_interface_type == WO_INET) { + char * port = "7712"; + if (arg != NULL && g_strlen((char *)arg) > 0) { + port = arg; + } + fd = g_tcp_socket(); + g_tcp_set_non_blocking(fd); + g_tcp_bind_flags(fd, port, AI_ADDRCONFIG | AI_PASSIVE); + } + else { + SAY("ERROR: g_interface_type = %d",g_interface_type); + } + g_trans = trans_create(g_trans_socket_type, MAX_STREAM, MAX_STREAM); + g_trans->trans_data_in = inpipe_data_in; + g_trans->callback_data = NULL; + g_trans->header_size = 0; + lres = trans_listen(g_trans, tpath); + fd = g_trans->sck; + g_tcp_set_non_blocking(fd); + while (!ready) { + g_obj_wait(&fd, 1, NULL, 0, 0); + if (g_is_wait_obj_set(fd)) { + fd = g_tcp_accept(g_trans->sck); + if (fd > -1) { + ready = 1; + } + } + } + g_trans->sck = fd; + g_trans->type1 = 2; + g_trans->ready = 1; + g_trans->running = 1; + TC_BARR_WAIT(barr_thread); + TC_BARR_WAIT(barr_loop); + while (g_trans == NULL || g_trans->ready < 1 || g_trans->running < 1 || g_trans->sck < 0 || g_trans->trans_data_in == NULL) { + g_sleep(400); + } + if (g_trans == NULL || g_trans->ready < 1 || g_trans->running < 1 || g_trans->sck < 0 || g_trans->trans_data_in == NULL) { + SAY("ERROR: not ready"); + } + else while (!done) { + tbus objs[24] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + ptrdiff_t count = 0; + int timeout = -1; + if (g_trans->lock != NULL) { + TC_MUTEX_LOCK(g_trans->lock); + g_trans->locked = 1; + locked = 1; + } + trans_get_wait_objs(g_trans, objs, &count, &timeout); + if (locked) { + g_trans->locked = 0; + TC_MUTEX_UNLOCK(g_trans->lock); + locked = 0; + } + if ((count > 0) && (g_obj_wait(objs, count, 0, 0, timeout) == 0)) { + ptrdiff_t i = 0; + unsigned char is_set = 0; + for (i = 0; i < count; i++) { + if (g_is_wait_obj_set(objs[i])) { + is_set = 1; + break; + } + } + if (is_set) { + if (tres = trans_check_wait_objs(g_trans) != 0) { + SAY("ERROR: trans_check_wait_objs() returned %d", tres); + done = 1; + } + else { + } + } + } + TC_MUTEX_LOCK(mutex_done); + if (done > 0) { + g_done = done; + } + done = g_done; + TC_MUTEX_UNLOCK(mutex_done); + } + + TC_MUTEX_LOCK(mutex_done); + g_done = 1; + TC_MUTEX_UNLOCK(mutex_done); + + end:; + if (locked) { + g_trans->locked = 0; + TC_MUTEX_UNLOCK(g_trans->lock); + locked = 0; + } + TC_THREAD_EXIT(NULL); + return rv; +} + +static void * APP_CC outpipe_loop(void * arg) { + void * rv = (void *)NULL; + unsigned char done = 0; + unsigned char loop_done = 0; + tbus fd = -1; + TC_BARR_WAIT(barr_thread); + while (!done) { + unsigned char cont = 0; + stream_list_t * entry = (stream_list_t *)NULL; + struct stream * s = (struct stream *)NULL; + int cnt = 0; + TC_MUTEX_LOCK(mutex_ilist); + if (!loop_done) { + TC_BARR_WAIT(barr_loop); + loop_done = 1; + if (g_trans_socket_type == WO_FIFO || g_trans_socket_type == 0) { + if (g_trans != NULL && g_trans->sck_out > -1) { + fd = g_trans->sck_out; + } + else { + if (!g_file_exist(outpipepath)) { + g_create_fifo(outpipepath); + } + fd = open(outpipepath, O_WRONLY | O_SYNC); + } + } + else if (g_trans_socket_type == WO_LOCAL || g_trans_socket_type == WO_INET) { + if (g_trans != NULL && g_trans->sck > -1) { + fd = g_trans->sck; + } + } + } + if (ilist_count < 1) { + g_ilist_waiting++; + TC_COND_WAIT(cond_ilist, mutex_ilist); + g_ilist_waiting--; + if (g_ilist_triggered < 1) { + cont = 1; + } + g_ilist_triggered = 0; + } + TC_MUTEX_UNLOCK(mutex_ilist); + if (cont > 0) { + continue; + } + TC_MUTEX_LOCK(mutex_ilist); + entry = NULL; + if (ilist_count > 0) { + SQ_DEQ(ilist, &entry); + ilist_count--; + } + if (entry == NULL) { + TC_MUTEX_UNLOCK(mutex_ilist); + SAY("deq'd entry is NULL"); + } + else { + size_t len = 0; + TC_MUTEX_UNLOCK(mutex_ilist); + s = entry->s; + len = (s == NULL || s->data == NULL || s->p == NULL || s->end == NULL || s->p < s->data || s->end <= s->p || s->size < 1 || (s->end - s->data) > s->size || (s->end - s->p) > s->size) ? 0 : (s->end - s->p); + if (fd > -1 && len > 0) { + tbus objs[1] = { -1 }; + if (g_trans != NULL) { + unsigned char locked = 0; + struct stream * ls = (struct stream *)NULL; + if (g_trans->lock != NULL) { + TC_MUTEX_LOCK(g_trans->lock); + g_trans->locked = 1; + locked = 1; + } + ls = trans_get_out_s(g_trans, MAX_STREAM); + if (((ls->end + len) - ls->data) <= MAX_STREAM) { + out_uint8a(ls, s->data, len); + s_mark_end(ls); + trans_force_write(g_trans); + } + if (locked) { + g_trans->locked = 0; + TC_MUTEX_UNLOCK(g_trans->lock); + locked = 0; + } + } + else { + if (g_trans_socket_type == WO_FIFO || g_trans_socket_type == 0) { + g_fifo_write(fd, s->data, len); + } + else if (g_trans_socket_type == WO_LOCAL || g_trans_socket_type == WO_INET) { + g_tcp_send_force(fd, s->data, len, 0); + } + } + } + if (s != NULL && s->data != NULL) { + free_stream(s); + s = (struct stream *)NULL; + } + } + TC_MUTEX_UNLOCK(mutex_ilist); + if (entry != NULL) { + g_free(entry); + entry = (stream_list_t *)NULL; + } + TC_MUTEX_LOCK(mutex_done); + done = g_done; + TC_MUTEX_UNLOCK(mutex_done); + } + if ((g_trans_socket_type == WO_FIFO || g_trans_socket_type == 0) && (fd > -1)) { + g_file_close(fd); + fd = -1; + } + end:; + TC_THREAD_EXIT(NULL); + return rv; +} + +static size_t APP_CC inpipe_data_in(struct trans * chan) { + size_t rv = 0; + tbus id = -1; + + if (chan == NULL) { + SAY("ERROR: chan is NULL"); + } + else if (chan->sck < 0) { + SAY("ERROR: socket is invalid"); + } + else if (g_done > 0) { + SAY("DEBUG: g_done is true"); + } + else { + unsigned char done = 0; + while (id < 0) { + TC_MUTEX_LOCK(mutex_id); + if (g_channel_id > -1) { + id = g_channel_id; + TC_MUTEX_UNLOCK(mutex_id); + break; + } + else { + const uint64_t tsec = 300; + TC_MUTEX_UNLOCK(mutex_id); + g_sleep(tsec); + } + } + TC_MUTEX_LOCK(mutex_done); + done = g_done; + TC_MUTEX_UNLOCK(mutex_done); + if (done < 1) { + handle_data(id, chan->sck); + } + } + + end:; + return rv; +} diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/dynamic/xrdp_drdynvc_interface.h posixrdp/posixxrdp.orig/sesman/dynamic/xrdp_drdynvc_interface.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/dynamic/xrdp_drdynvc_interface.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/dynamic/xrdp_drdynvc_interface.h 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,51 @@ +#if !defined(XRDP_DRDYNVC_INTERFACE_H) +#define XRDP_DRDYNVC_INTERFACE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "defines.h" +#include "arch.h" +#include "crc32.h" +#include "parse.h" +#include "os_calls.h" +#include "rdpdr.h" +#include "rdpdr_methods.h" +#include "stream_list.h" +#include "thread_calls.h" +#include "thread_macros.h" +#include "trans.h" +#include "drdynvc_defs.h" + +#if !defined(SAY) +#define SAY(...) { \ + char cbuf[4096]; \ + g_memset(cbuf,0,sizeof(cbuf)); \ + g_snprintf(cbuf,sizeof(cbuf),__VA_ARGS__); \ + TC_MUTEX_LOCK(mutex_say); \ + g_writeln("[%s() @ line %d]: %s", __func__, __LINE__, cbuf); \ + TC_MUTEX_UNLOCK(mutex_say); \ +} +#endif + +#if !defined(TC_COND_REINIT) +#define TC_COND_REINIT(x) { \ + tc_t tattr; \ + tc_p pattr = &tattr; \ + g_memset(pattr,0,sizeof(tc_t)); \ + g_memset(x, 0, sizeof(tc_t)); \ + TC_CONDATTR_INIT(pattr); \ + TC_CONDATTR_SETPSHARED(pattr, TC_PROCESS_SHARED); \ + TC_COND_CREATE(x, pattr); \ +} +#endif + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/dynamic/xrdp_rdpeai.c posixrdp/posixxrdp.orig/sesman/dynamic/xrdp_rdpeai.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/dynamic/xrdp_rdpeai.c 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/dynamic/xrdp_rdpeai.c 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,1452 @@ +#include "xrdp_rdpeai.h" +#include "stream_list.h" +#include "dbg.h" + +#include +#include + +static volatile unsigned char g_is_child = 0; +static void * g_pa_args[2] = { NULL, NULL }; + +static tc_t g_chan_thread; +static tc_p thread_chan = &g_chan_thread; +static tc_t g_pa_thread; +static tc_p thread_pa = &g_pa_thread; + +static tc_t g_done_mutex = TC_MUTEX_INITIALIZER; +static tc_p mutex_done = &g_done_mutex; +static tc_t g_trans_mutex = TC_MUTEX_INITIALIZER; +static tc_p mutex_trans = &g_trans_mutex; +static tc_t g_pa_trans_mutex = TC_MUTEX_INITIALIZER; +static tc_p mutex_pa_trans = &g_pa_trans_mutex; +static tc_t g_formats_mutex = TC_MUTEX_INITIALIZER; +static tc_p mutex_formats = &g_formats_mutex; +static tc_t g_pending_mutex = TC_MUTEX_INITIALIZER; +static tc_p mutex_pending = &g_pending_mutex; +static tc_t g_pending_cond; +static tc_p cond_pending = &g_pending_cond; +static tc_t g_pa_mutex = TC_MUTEX_INITIALIZER; +static tc_p mutex_pa = &g_pa_mutex; +static tc_t g_pa_cond; +static tc_p cond_pa = &g_pa_cond; +static tc_t g_open_mutex = TC_MUTEX_INITIALIZER; +static tc_p mutex_open = &g_open_mutex; +static tc_t g_open_cond; +static tc_p cond_open = &g_open_cond; + +static tc_t g_thread_barr; +static tc_p barr_thread = &g_thread_barr; +static tc_t g_version_barr; +static tc_p barr_version = &g_version_barr; +static tc_t g_formats_barr; +static tc_p barr_formats = &g_formats_barr; +static tc_t g_open_barr; +static tc_p barr_open = &g_open_barr; +static tc_t g_misc_barr; +static tc_p barr_misc = &g_misc_barr; + +static const char sockpath[] = "/tmp/.audio_input_socket"; +static const char inpipepath[] = "/tmp/audio_input_inpipe"; +static const char outpipepath[] = "/tmp/audio_input_outpipe"; + +static volatile unsigned char g_done = 0; +static volatile unsigned char g_version_done = 0; +static volatile unsigned char g_formats_done = 0; +static volatile unsigned char g_misc_done = 0; +static volatile unsigned char g_open = 0; +static volatile unsigned int g_open_pending = 0; +static volatile unsigned int g_open_waiting = 0; +static volatile unsigned char g_pending = 0; +static volatile unsigned int g_pending_waiting = 0; +static volatile unsigned int g_pa_waiting = 0; +static volatile ptrdiff_t g_pa_count = 0; +static rdpeai_interface_t g_interface_type = RDPEAI_SOCKET; + +static volatile unsigned char g_sound_up = 0; + +static stream_list_t * ilist = (stream_list_t *)NULL; +static stream_list_t * olist = (stream_list_t *)NULL; +static volatile int ilist_count = 0; +static volatile int olist_count = 0; + +static struct stream * g_ins = (struct stream *)NULL; +static struct stream * g_pa_stream = (struct stream *)NULL; +static tbus g_fd_in = -1; +static tbus g_fd_out = -1; +static tbus g_fd_log = -1; +static int g_uniqid = 0; +static volatile tbus g_channel_id = -1; + +static const unsigned int g_trans_socket_type = WO_LOCAL; +static struct trans * g_trans = (struct trans *)NULL; +static int dynamic_channel_id = -1; + +static struct trans * g_pa_trans = (struct trans *)NULL; + +static size_t g_client_format_count = 0; +static ptrdiff_t g_client_format_index = -1; +static AUDIO_FORMAT_REC * g_client_formats = (AUDIO_FORMAT_REC *)NULL; +static AUDIO_FORMAT_REC * g_audio_format = (AUDIO_FORMAT_REC *)NULL; + +static AUDIO_FORMAT_REC rdpeai_audio_formats[] = RDPEAI_FORMATS_DEFAULT; + +#define NUM_THREADS 2 + +static tbus g_pfd = -1; + + +int APP_CC main(int, char * []); +static tbus APP_CC connect_transport(tbus *, tbus *, const char *, const char *, const char *, const char *); +static tbus APP_CC launch_child(void); +static int APP_CC handle_initialization(struct trans *); +static int APP_CC handle_open(struct trans *); +static int APP_CC handle_finish(struct trans *); +static int APP_CC handle_formats(struct trans *); +static int APP_CC launch_threads(struct trans *); +static size_t APP_CC chan_data_in(struct trans *); +static void * APP_CC chan_loop(void *); +static int APP_CC launch_pa(pa_simple **); +static int APP_CC stop_pa(pa_simple **); +static void * APP_CC pa_output_loop(void *); +static size_t APP_CC pa_data_in(struct trans *); +static int APP_CC sound_get_pulseaudio_server(const char **); + + +/* PulseAudio */ +#define SPEC_PCM { .format = PA_SAMPLE_S16LE, .rate = 44100, .channels = 2 }; +#define SPEC_PCM_MONO { .format = PA_SAMPLE_S16LE, .rate = 44100, .channels = 1 }; +#define SPEC_ULAW { .format = PA_SAMPLE_ULAW, .rate = 44100, .channels = 2, } +#define SPEC_ULAW_MONO { .format = PA_SAMPLE_ULAW, .rate = 44100, .channels = 1, } +#define SPEC_ULAW_LOW { .format = PA_SAMPLE_ULAW, .rate = 11025, .channels = 2, } +#define SPEC_ALAW { .format = PA_SAMPLE_ALAW, .rate = 44100, .channels = 2, } +#define SPEC_ALAW_MONO { .format = PA_SAMPLE_ALAW, .rate = 44100, .channels = 1, } +#define SPEC_IMA_ADPCM SPEC_PCM +static pa_sample_spec sample_spec = SPEC_ULAW_LOW; +static pa_simple * g_pa = (pa_simple *)NULL; + + + +int APP_CC main(int argc, char * argv[]) { + int rv = 0; + tbus fd_in = -1; + tbus fd_out = -1; + tbus fd_log = -1; + char * caddr = (char *)NULL; + char * cport = (char *)NULL; + char * oaddr = (char *)NULL; + char * oport = (char *)NULL; + unsigned char done = 0; + + make_stream(g_ins); + init_stream(g_ins, MAX_STREAM); + + make_stream(g_pa_stream); + init_stream(g_pa_stream, MAX_STREAM); + + { + tc_t lattr; + tc_p attr = &lattr; + g_memset(attr,0,sizeof(tc_t)); + TC_CONDATTR_INIT(attr); + TC_COND_CREATE(cond_pending, attr); + TC_COND_CREATE(cond_open, attr); + TC_COND_CREATE(cond_pa, attr); + } + { + tc_t lattr; + tc_p attr = &lattr; + g_memset(attr,0,sizeof(tc_t)); + TC_MUTATTR_INIT(attr); + TC_MUTATTR_SETTYPE(attr, TC_MUTEX_ERRORCHECK); + TC_MUTEX_INIT(mutex_pending, attr); + TC_MUTEX_INIT(mutex_open, attr); + TC_MUTEX_INIT(mutex_pa, attr); + TC_MUTEX_INIT(mutex_done, attr); + TC_MUTEX_INIT(mutex_trans, attr); + TC_MUTEX_INIT(mutex_formats, attr); + TC_MUTEX_INIT(mutex_pa_trans, attr); + } + + g_pfd = launch_child(); + if (g_pfd < 0 || g_is_child > 0) { + rv = 0; + goto end; + } + + if (argc > 1 && argv[1] != NULL && g_strlen(argv[1]) > 0) { + char * cpos = (char *)NULL; + cpos = g_strchr(argv[1],':'); + if (cpos == NULL) { + caddr = g_strndup(argv[1],64); + } + else { + cport = g_strndup(cpos,10); + caddr = g_strndup(argv[1],(cpos - argv[1])); + } + if (cport == NULL || g_strlen(cport) == 0) { + g_interface_type = RDPEAI_SOCKET; + } + else { + g_interface_type = RDPEAI_INET; + } + } + if (argc > 2 && argv[2] != NULL && g_strlen(argv[2]) > 0) { + char * cpos = (char *)NULL; + cpos = g_strchr(argv[2],':'); + if (cpos == NULL) { + oaddr = g_strndup(argv[2],64); + } + else { + oport = g_strndup(cpos,10); + oaddr = g_strndup(argv[2],(cpos - argv[2])); + } + } + if (argc < 2) { + g_fd_in = STDIN_FILENO; + g_fd_out = STDOUT_FILENO; + fd_in = g_fd_in; + fd_out = g_fd_out; + g_interface_type = 0; + } + if (connect_transport(&fd_in, &fd_out, caddr, cport, oaddr, oport) > -1) { + g_fd_in = fd_in; + g_fd_out = fd_out; + } + else { + SAY("failed to establish connection (rv = %d, fd_out = %d)", rv, fd_out); + rv = -1; + g_done = 1; + g_fd_out = -1; + goto end; + } + + g_memset(barr_thread, 0, sizeof(tc_t)); + TC_BARR_INIT(barr_thread, (NUM_THREADS + 1)); + g_memset(barr_version, 0, sizeof(tc_t)); + TC_BARR_INIT(barr_version, NUM_THREADS); + g_memset(barr_formats, 0, sizeof(tc_t)); + TC_BARR_INIT(barr_formats, NUM_THREADS); + g_memset(barr_misc, 0, sizeof(tc_t)); + TC_BARR_INIT(barr_misc, NUM_THREADS); + g_memset(barr_open, 0, sizeof(tc_t)); + TC_BARR_INIT(barr_open, NUM_THREADS); + + launch_threads(g_trans); + TC_BARR_WAIT(barr_thread); + + TC_MUTEX_LOCK(mutex_trans); + handle_initialization(g_trans); + TC_MUTEX_UNLOCK(mutex_trans); + TC_BARR_WAIT(barr_version); + + TC_MUTEX_LOCK(mutex_trans); + handle_formats(g_trans); + TC_MUTEX_UNLOCK(mutex_trans); + TC_BARR_WAIT(barr_formats); + + TC_MUTEX_LOCK(mutex_trans); + handle_open(g_trans); + TC_MUTEX_UNLOCK(mutex_trans); + TC_BARR_WAIT(barr_open); + + TC_BARR_WAIT(barr_misc); + + TC_MUTEX_LOCK(mutex_trans); + handle_finish(g_trans); + TC_MUTEX_UNLOCK(mutex_trans); + + stop_pa(&g_pa); + + TC_THREAD_JOIN(thread_pa->thread, NULL); + TC_THREAD_JOIN(thread_chan->thread, NULL); + + end:; + if (g_fd_log > -1) { + g_file_close(g_fd_log); + } + g_sleep(200); + return rv; +} + + +static int APP_CC launch_pa(pa_simple ** s) { + int rv = 0; + const char * server = (const char *)NULL; + if (s == NULL) { + SAY("ERROR: *s is NULL"); + rv = -1; + goto end; + } + else { + int error = 0; + //sound_get_pulseaudio_server(&server); + *s = pa_simple_new( + server, /* const char * server, */ + "xrdp_sndin", /* const char * name, */ + PA_STREAM_PLAYBACK, /* pa_stream_direction_t dir, */ + NULL, /* const char * dev, */ + "sndin", /* const char * stream_name, */ + &sample_spec, /* const pa_sample_spec * ss, */ + NULL, /* const pa_channel_map * map, */ + NULL, /* const pa_buffer_attr * attr, */ + &error /* int * error */ + ); + if (*s == NULL) { + SAY("ERROR: pa_simple_new() failed [error = %d]",error); + rv = -1; + goto end; + } + } + end:; + return rv; +} + +static int APP_CC stop_pa(pa_simple ** s) { + int rv = 0; + if (s != NULL && *s != NULL) { + pa_simple_free(*s); + } + return rv; +} + + +static int APP_CC launch_threads(struct trans * chan) { + int rv = 0; + tc_t attr; + tc_p pattr = &attr; + + g_memset(pattr, 0, sizeof(tc_t)); + TC_THREADATTR_INIT(pattr); + TC_THREADATTR_SETDETACHSTATE(pattr, TC_CREATE_JOINABLE); + TC_THREAD_INIT_FULL(&(thread_chan->thread), &(pattr->threadattr), &chan_loop, chan); + TC_THREAD_INIT_FULL(&(thread_pa->thread), &(pattr->threadattr), &pa_output_loop, g_pa); + + end:; + return rv; +} + +static tbus APP_CC connect_transport(tbus * fd_in, tbus * fd_out, const char * iaddress, const char * iport, const char * oaddress, const char * oport) { + tbus rv = -1; + unsigned char is_local = 0; + unsigned char is_fifo = 0; + unsigned char is_stdio = 0; + unsigned char locked = 0; + char * addr = "localhost"; + char * port = "7712"; + + TC_MUTEX_LOCK(mutex_trans); + + if ((iaddress == NULL || g_strlen(iaddress) == 0) && (iport == NULL || g_strlen(iport) == 0)) { + is_stdio = 1; + addr = (char *)NULL; + port = (char *)NULL; + g_interface_type == 0; + } + else { + if (iaddress != NULL && g_strlen(iaddress) > 0) { + addr = (char *)iaddress; + } + if (iport != NULL && g_strlen(iport) > 0) { + port = (char *)iport; + } + } + if (g_interface_type == RDPEAI_FIFO) { + is_fifo = 1; + } + else { + is_fifo = 0; + } + if (addr != NULL && g_strlen(addr) > 0 && g_strchr(addr, '/') != NULL) { + is_local = 1; + } + else { + is_local = 0; + } + if (is_stdio) { + SAY("(using stdout)"); + g_trans = trans_create(0, MAX_STREAM, MAX_STREAM); + if (g_trans != NULL && g_trans->lock != NULL) { + TC_MUTEX_LOCK(g_trans->lock); + g_trans->locked = 1; + locked = 1; + } + trans_connect(g_trans, NULL, NULL, 0); + *fd_in = g_trans->sck; + *fd_out = g_trans->sck_out; + } + else if (is_fifo) { + SAY("(using fifo)"); + if (addr == NULL || g_strlen(addr) < 1) { + SAY("ERROR: path is empty for fifo"); + *fd_in = -1; + *fd_out = -1; + rv = -1; + } + else if (*fd_out = g_fifo_open(addr) < 1) { + SAY("ERROR: g_fifo_open(\"%s\") failed",addr); + *fd_in = -2; + *fd_out = -2; + rv = -2; + } + if (oaddress == NULL || g_strlen(oaddress) < 1) { + SAY("ERROR: path is empty for fifo"); + *fd_in = -1; + *fd_out = -1; + rv = -1; + } + else if (*fd_out = g_fifo_open(oaddress) < 1) { + SAY("ERROR: g_fifo_open(\"%s\") failed",oaddress); + *fd_in = -2; + *fd_out = -2; + rv = -2; + } + g_trans = trans_create(WO_FIFO, MAX_STREAM, MAX_STREAM); + if (g_trans != NULL && g_trans->lock != NULL) { + TC_MUTEX_LOCK(g_trans->lock); + g_trans->locked = 1; + locked = 1; + } + trans_attach(g_trans, *fd_out); + g_trans->sck = *fd_in; + g_trans->sck_out = *fd_out; + } + else if (is_local) { + SAY("(using local socket)"); + if ((*fd_out = g_tcp_local_socket()) < 1) { + *fd_out = -2; + rv = -2; + } + else { + rv = g_tcp_local_connect(*fd_out, addr); + } + g_trans = trans_create(WO_LOCAL, MAX_STREAM, MAX_STREAM); + if (g_trans != NULL && g_trans->lock != NULL) { + TC_MUTEX_LOCK(g_trans->lock); + g_trans->locked = 1; + locked = 1; + } + trans_attach(g_trans, *fd_out); + g_tcp_set_non_blocking(g_trans->sck); + } + else { + if ((*fd_out = g_tcp_socket()) < 1) { + rv = -2; + } + else { + rv = g_tcp_connect(*fd_out, addr, port); + } + g_trans = trans_create(WO_INET, MAX_STREAM, MAX_STREAM); + if (g_trans != NULL && g_trans->lock != NULL) { + TC_MUTEX_LOCK(g_trans->lock); + g_trans->locked = 1; + locked = 1; + } + trans_attach(g_trans, *fd_in); + g_tcp_set_non_blocking(g_trans->sck); + } + + if (g_trans != NULL) { + g_trans->trans_data_in = chan_data_in; + g_trans->callback_data = g_trans; + g_trans->header_size = 0; + g_trans->ready = 1; + g_trans->running = 1; + } + + rv = *fd_out; + + end:; + if (locked) { + g_trans->locked = 0; + TC_MUTEX_UNLOCK(g_trans->lock); + locked = 0; + } + TC_MUTEX_UNLOCK(mutex_trans); + return rv; +} + +static void * APP_CC chan_loop(void * arg) { + void * rv = (void *)NULL; + struct trans * chan = (struct trans *)NULL; + int tres = 0; + unsigned char done = 0; + unsigned char barrier_done = 0; + SAY("called"); + if (arg != NULL) { + chan = (struct trans *)arg; + } + if (chan == NULL) { + TC_MUTEX_LOCK(mutex_trans); + chan = g_trans; + TC_MUTEX_UNLOCK(mutex_trans); + } + if (chan == NULL) { + SAY("ERROR: chan is NULL"); + } + else while (!done) { + tbus objs[24] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + ptrdiff_t count = 0; + int timeout = -1; + unsigned char locked = 0; + if (!barrier_done) { + TC_BARR_WAIT(barr_thread); + barrier_done = 1; + } + if (chan->lock != NULL) { + TC_MUTEX_LOCK(chan->lock); + chan->locked = 1; + locked = 1; + } + TC_MUTEX_LOCK(mutex_trans); + trans_get_wait_objs(chan, objs, &count, &timeout); + if (locked) { + chan->locked = 0; + TC_MUTEX_UNLOCK(chan->lock); + locked = 0; + } + TC_MUTEX_UNLOCK(mutex_trans); + if ((count > 0) && (g_obj_wait(objs, count, 0, 0, timeout) == 0)) { + ptrdiff_t i = 0; + unsigned char is_set = 0; + //SAY("count = %d",count); + for (i = 0; i < count; i++) { + if (g_is_wait_obj_set(objs[i])) { + is_set = 1; + break; + } + } + TC_MUTEX_LOCK(mutex_trans); + TC_MUTEX_LOCK(chan->lock); + if ((is_set > 0) && (tres = trans_check_wait_objs(chan)) != 0) { + SAY("ERROR: trans_check_wait_objs() returned %d", tres); + done = 1; + } + TC_MUTEX_UNLOCK(chan->lock); + TC_MUTEX_UNLOCK(mutex_trans); + } + TC_MUTEX_LOCK(mutex_done); + if (done > 0) { + g_done = done; + } + done = g_done; + TC_MUTEX_UNLOCK(mutex_done); + } + end:; + TC_BARR_WAIT(barr_misc); + SAY("done."); + TC_THREAD_EXIT(NULL); + return rv; +} + +static size_t APP_CC chan_data_in(struct trans * chan) { + size_t rv = 0; + unsigned char locked = 0; + //SAY("DEBUG: called"); + if (chan == NULL) { + SAY("ERROR: chan is NULL"); + } + else { + ptrdiff_t len = 0; + struct stream * s = (struct stream *)NULL; + if (0 && chan->lock != NULL) { + TC_MUTEX_LOCK(chan->lock); + chan->locked = 1; + locked = 1; + } + trans_force_read(chan, 3); + s = trans_get_in_s(chan); + if (s == NULL) { + SAY("ERROR: input stream is NULL"); + } + else { + BYTE opcode = 0x00; + in_uint8s(s, 2) + in_uint8(s, opcode); + switch (opcode) { + case CMSG_SNDIN_VERSION: + SAY(" ** MSG_SNDIN_VERSION"); + { + trans_force_read(chan, 4); + g_reset_wait_obj(chan->sck); + if (!g_version_done) { + g_version_done = 1; + TC_BARR_WAIT(barr_version); + } + } + break; + case CMSG_SNDIN_FORMATS: + SAY(" ** MSG_SNDIN_FORMATS"); + { + DWORD count = 0; + DWORD size = 0; + ptrdiff_t rem = (MAX_STREAM - 8); + struct stream * ls = (struct stream *)NULL; + void * tp = (void *)NULL; + trans_force_read(chan, 8); + in_uint32_le(s, count); + in_uint32_le(s, size); + if (size > 9) { + const size_t relsize = (const size_t)(size - 9); + assert(count > 0); + tp = (void *)(s->p); + trans_force_read(chan, relsize); + rem -= ((MAX_STREAM >= relsize) ? relsize : 0); + ls = (struct stream *)g_malloc(sizeof(struct stream), 1); + g_memcpy(ls, s, sizeof(struct stream)); + s->data = (char *)g_malloc(s->size, 1); + s->p = s->data + (ls->p - ls->data); + s->end = s->data + (ls->end - ls->data); + } + if (rem > 0) { + trans_read(chan, MIN(rem, (s->size - (s->p - s->data)))); + } + TC_MUTEX_LOCK(mutex_pending); + if (g_pending > 0) { + g_pending = 0; + } + if (g_pending_waiting > 0) { + if (g_pending_waiting > 1) { + TC_COND_BROADCAST(cond_pending); + } + else { + TC_COND_SIGNAL(cond_pending); + } + } + TC_MUTEX_UNLOCK(mutex_pending); + /* Process the sound formats received from the client */ + TC_MUTEX_LOCK(mutex_formats); + g_client_format_count = count; + if (g_client_format_count > 0 && tp != NULL) { + g_client_formats = (AUDIO_FORMAT_REC *)tp; + g_client_format_index = 0; + g_audio_format = (AUDIO_FORMAT_REC *)tp; + assert(g_audio_format == &(g_client_formats[g_client_format_index])); + SAY("DEBUG: audio format = 0x%8.8x",g_audio_format->wFormatTag); + } + else { + SAY("ERROR: failed to negotiate a common audio format between the client and server"); + } + /* Trigger the "barr_formats" barrier in order to proceed with subsequent operation */ + if (g_formats_done < 1) { + g_formats_done = 1; + TC_MUTEX_UNLOCK(mutex_formats); + TC_BARR_WAIT(barr_formats); + } + else { + TC_MUTEX_UNLOCK(mutex_formats); + } + } + break; + case CMSG_SNDIN_OPEN: + SAY(" ** MSG_SNDIN_OPEN"); + { + SAY("ERROR: invalid opcode (MS-RDPEAI does not permit a client to transmit a MSG_SNDIN_OPEN pdu to the server)"); + trans_read(chan, MAX_STREAM); + } + break; + case CMSG_SNDIN_OPEN_REPLY: + SAY(" ** MSG_SNDIN_OPEN_REPLY"); + { + HRESULT res = 0x00000000; + unsigned char already_opened = 0; + trans_force_read(chan, 4); + in_uint32_le(s, res); + SAY("INFO: Result = 0x%8.8x",res); + TC_MUTEX_LOCK(mutex_open); + if (g_open < 1) { + already_opened = 0; + } + else { + already_opened = 1; + } + if (g_open < 1 && g_open_pending > 0) { + g_open = 1; + g_open_pending--; + } + if (g_open > 0 && g_open_waiting > 0) { + if (g_open_waiting > 1) { + TC_COND_BROADCAST(cond_open); + } + else { + TC_COND_SIGNAL(cond_open); + } + } + TC_MUTEX_UNLOCK(mutex_open); + if (already_opened < 1) { + TC_BARR_WAIT(barr_open); + } + } + break; + case CMSG_SNDIN_DATA_INCOMING: + //SAY(" ** MSG_SNDIN_DATA_INCOMING"); + { + TC_MUTEX_LOCK(mutex_pending); + g_pending++; + TC_MUTEX_UNLOCK(mutex_pending); + } + break; + case CMSG_SNDIN_DATA: + //SAY(" ** MSG_SNDIN_DATA"); + { + ptrdiff_t llen = 0; + trans_read(chan, MAX_STREAM); + if ((s->end > s->p) && (s->end != NULL) && (s->p != NULL) && ((s->end - s->p) > 0)) { + llen = (s->end - s->p); + } + TC_MUTEX_LOCK(mutex_pending); + if (g_pending > 0) { + g_pending--; + } + if (g_pending_waiting > 0) { + if (g_pending_waiting > 1) { + TC_COND_BROADCAST(cond_pending); + } + else { + TC_COND_SIGNAL(cond_pending); + } + } + TC_MUTEX_UNLOCK(mutex_pending); + TC_MUTEX_LOCK(mutex_pa); + if (llen > 0) { + uint32_t * pnum = (uint32_t *)(g_pa_stream->data); + if (g_pa_count == 0) { + g_pa_stream->p = g_pa_stream->end = g_pa_stream->data; + g_pa_stream->p += 4; + g_pa_stream->end = g_pa_stream->p; + *pnum = 0x00000000; + } + g_memcpy(g_pa_stream->p, s->p, llen); + g_pa_stream->p += llen; + g_pa_stream->end = g_pa_stream->p; + *pnum += llen; + g_pa_count++; + + if (llen > 0 && g_fd_log > -1) { + g_file_write(g_fd_log, s->p, llen); + } + + if (*pnum > (MAX_STREAM / 2)) { + g_pa_stream->p = g_pa_stream->data; + if (g_pa_trans != NULL && g_pa_trans->sck > -1) { + struct stream * ls = (struct stream *)NULL; + TC_MUTEX_LOCK(g_pa_trans->lock); + g_pa_trans->locked = 1; + //ls = trans_get_out_s(g_pa_trans, (*pnum + 4)); + g_pa_trans->out_s = g_pa_stream; + SAY("sending %d bytes to child",*pnum); + trans_force_write(g_pa_trans); + g_pa_trans->locked = 0; + TC_MUTEX_UNLOCK(g_pa_trans->lock); + } + g_pa_stream->p = g_pa_stream->data; + g_pa_count = 0; + *pnum = 0; + } + } + if (g_pa_waiting > 0 && g_pa_count > 6) { + if (g_pa_waiting > 1) { + TC_COND_BROADCAST(cond_pa); + } + else { + TC_COND_SIGNAL(cond_pa); + } + } + TC_MUTEX_UNLOCK(mutex_pa); + } + break; + case CMSG_SNDIN_FORMATCHANGE: + SAY(" ** MSG_SNDIN_FORMATCHANGE"); + { + uint32_t newidx = 0; + if (g_client_format_index > -1 && g_client_format_index < g_client_format_count) { + newidx = g_client_format_index; + } + trans_force_read(chan, 4); + in_uint32_le(s, newidx); + SAY("received format index = %d", newidx); + if (newidx >= 0 && newidx <= g_client_format_count) { + g_client_format_index = newidx; + g_audio_format = (&(g_client_formats[g_client_format_index])); + } + SAY("new format index = %d (wFormatTag = 0x%8.8x)", newidx, g_client_formats[g_client_format_index].wFormatTag); + } + break; + default: + SAY(" ** ERROR: unrecognized instruction (opcode = 0x%8.8x)",opcode); + break; + } + len = s->end - s->data; + //SAY("(len = %d)",len); + if (len > 0) { + //g_hexdump_file("/tmp/taskq_hex_RDPEAI_CHAN_DATA_IN.hexdump",(s->data + chan->header_size),len); + } + } + } + end:; + if (locked) { + chan->locked = 0; + TC_MUTEX_UNLOCK(chan->lock); + locked = 0; + } + //SAY("done (g_version_done = %d, g_formats_done = %d).",g_version_done,g_formats_done); + return rv; +} + +static int APP_CC handle_initialization(struct trans * chan) { + int rv = 0; + struct stream * s = (struct stream *)NULL; + unsigned char locked = 0; + unsigned char ready = 0; + + SAY("called"); + + if (chan == NULL) { + SAY("ERROR: chan is NULL"); + rv = -1; + goto end; + } + while (!ready) { + if (chan->lock != NULL) { + TC_MUTEX_LOCK(chan->lock); + chan->locked = 1; + locked = 1; + } + if (chan->ready > 0 && chan->running > 0 && chan->status == 1) { + ready = 1; + } + if (locked) { + chan->locked = 0; + TC_MUTEX_UNLOCK(chan->lock); + locked = 0; + } + if (!ready) { + g_sleep(300); + } + } + if (chan->lock != NULL) { + TC_MUTEX_LOCK(chan->lock); + chan->locked = 1; + locked = 1; + } + s = trans_get_out_s(chan, MAX_STREAM); + if (s == NULL) { + SAY("ERROR: s is NULL"); + rv = -1; + goto end; + } + else { + ptrdiff_t len = 0; + MSG_SNDIN_VERSION * pdu = (MSG_SNDIN_VERSION *)NULL; + pdu = (MSG_SNDIN_VERSION *)g_malloc(sizeof(MSG_SNDIN_VERSION), 1); + if (pdu == NULL) { + SAY("ERROR: pdu is NULL"); + goto end; + } + else { + construct_MSG_SNDIN_VERSION(pdu); + send_MSG_SNDIN_VERSION(pdu, s); + } + s_mark_end(s); + len = s->end - s->data; + if (len > 0) { + ptrdiff_t tres = 0; + //g_hexdump_file("/tmp/taskq_hex_MSG_SNDIN_VERSION.hexdump", s->data, len); + if (chan->mode == 3 || chan->mode == 0) { + SAY("about to call trans_force_write(): (chan->sck_out = %d, len = %d)", chan->sck_out, len); + } + if ((g_interface_type == 0 || g_interface_type == 3) || ((g_interface_type == 1 || g_interface_type == 2) && g_tcp_socket_ok(chan->sck) && g_tcp_can_send(chan->sck, 300))) { + SAY("about to call trans_force_write(): (chan->sck = %d, chan->sck_out = %d, len = %d)", chan->sck, chan->sck_out, len); + tres = trans_force_write(chan); + SAY("trans_force_write() returned (tres = %d)",tres); + } + else { + SAY("ERROR: unable to send (g_interface_type = %d)", g_interface_type); + } + } + if (pdu != NULL) { + g_free(pdu); + pdu = (MSG_SNDIN_VERSION *)NULL; + } + } + + end:; + if (locked) { + chan->locked = 0; + TC_MUTEX_UNLOCK(chan->lock); + locked = 0; + } + SAY("done."); + return rv; +} + +static int APP_CC handle_formats(struct trans * chan) { + int rv = 0; + struct stream * s = (struct stream *)NULL; + unsigned char locked = 0; + unsigned char ready = 0; + + SAY("called"); + + if (chan == NULL) { + SAY("ERROR: chan is NULL"); + rv = -1; + goto end; + } + while (!ready) { + if (chan->lock != NULL) { + TC_MUTEX_LOCK(chan->lock); + chan->locked = 1; + locked = 1; + } + if (chan->ready > 0 && chan->running > 0 && chan->status == 1) { + ready = 1; + } + if (locked) { + chan->locked = 0; + TC_MUTEX_UNLOCK(chan->lock); + locked = 0; + } + if (!ready) { + g_sleep(300); + } + } + if (chan->lock != NULL) { + TC_MUTEX_LOCK(chan->lock); + chan->locked = 1; + locked = 1; + } + s = trans_get_out_s(chan, MAX_STREAM); + if (s == NULL) { + SAY("ERROR: s is NULL"); + rv = -1; + goto end; + } + else { + ptrdiff_t len = 0; + MSG_SNDIN_FORMATS * pdu = (MSG_SNDIN_FORMATS *)NULL; + pdu = (MSG_SNDIN_FORMATS *)g_malloc((sizeof(MSG_SNDIN_FORMATS) + (sizeof(AUDIO_FORMAT_REC) * RDPEAI_NUM_FORMATS)), 1); + if (pdu == NULL) { + SAY("ERROR: pdu is NULL"); + goto end; + } + else { + ptrdiff_t i = 0; + AUDIO_FORMAT_REC * fmt = (AUDIO_FORMAT_REC *)NULL; + DWORD * pnum = (DWORD *)NULL; + construct_MSG_SNDIN_FORMATS(pdu); + pdu->NumFormats = RDPEAI_NUM_FORMATS; + pnum = (DWORD *)NULL; + pdu->cbSizeFormatsPacket = sizeof(MSG_SNDIN_FORMATS) + (sizeof(AUDIO_FORMAT_REC) * pdu->NumFormats); + for (i = 0; i < pdu->NumFormats; i++) { + fmt = &(pdu->SoundFormats[i]); + g_memcpy(fmt, &(rdpeai_audio_formats[i]), sizeof(AUDIO_FORMAT_REC)); + } + send_MSG_SNDIN_FORMATS(pdu, s); + } + s_mark_end(s); + len = s->end - s->data; + if (len > 0) { + ptrdiff_t tres = 0; + //g_hexdump_file("/tmp/taskq_hex_MSG_SNDIN_FORMATS.hexdump", s->data, len); + if (chan->mode == 3 || chan->mode == 0) { + SAY("about to call trans_force_write(): (chan->sck_out = %d, len = %d)", chan->sck_out, len); + } + if ((g_interface_type == 0 || g_interface_type == 3) || ((g_interface_type == 1 || g_interface_type == 2) && g_tcp_socket_ok(chan->sck) && g_tcp_can_send(chan->sck, 300))) { + SAY("about to call trans_force_write(): (chan->sck = %d, chan->sck_out = %d, len = %d)", chan->sck, chan->sck_out, len); + tres = trans_force_write(chan); + SAY("trans_force_write() returned (tres = %d)",tres); + } + else { + SAY("ERROR: unable to send (g_interface_type = %d)", g_interface_type); + } + } + if (pdu != NULL) { + g_free(pdu); + pdu = (MSG_SNDIN_FORMATS *)NULL; + } + } + + end:; + if (locked) { + chan->locked = 0; + TC_MUTEX_UNLOCK(chan->lock); + locked = 0; + } + SAY("done."); + return rv; +} + +static int APP_CC handle_open(struct trans * chan) { + int rv = 0; + struct stream * s = (struct stream *)NULL; + unsigned char locked = 0; + unsigned char ready = 0; + + SAY("called"); + + if (chan == NULL) { + SAY("ERROR: chan is NULL"); + rv = -1; + goto end; + } + while (!ready) { + if (chan->lock != NULL) { + TC_MUTEX_LOCK(chan->lock); + chan->locked = 1; + locked = 1; + } + if (chan->ready > 0 && chan->running > 0 && chan->status == 1) { + ready = 1; + } + if (locked) { + chan->locked = 0; + TC_MUTEX_UNLOCK(chan->lock); + locked = 0; + } + if (!ready) { + g_sleep(300); + } + } + if (chan->lock != NULL) { + TC_MUTEX_LOCK(chan->lock); + chan->locked = 1; + locked = 1; + } + s = trans_get_out_s(chan, MAX_STREAM); + if (s == NULL) { + SAY("ERROR: s is NULL"); + rv = -1; + goto end; + } + else { + ptrdiff_t len = 0; + MSG_SNDIN_OPEN * pdu = (MSG_SNDIN_OPEN *)NULL; + pdu = (MSG_SNDIN_OPEN *)g_malloc(sizeof(MSG_SNDIN_OPEN), 1); + if (pdu == NULL) { + SAY("ERROR: pdu is NULL"); + goto end; + } + else { + construct_MSG_SNDIN_OPEN(pdu); + TC_MUTEX_LOCK(mutex_formats); + pdu->initialFormat = g_client_format_index + 1; + pdu->wFormatTag = g_audio_format->wFormatTag; + pdu->nChannels = g_audio_format->nChannels; + pdu->nSamplesPerSec = g_audio_format->nSamplesPerSec; + pdu->nAvgBytesPerSec = g_audio_format->nAvgBytesPerSec; + pdu->nBlockAlign = g_audio_format->nBlockAlign; + pdu->wBitsPerSample = g_audio_format->wBitsPerSample; + pdu->cbSize = g_audio_format->cbSize; + pdu->FramesPerPacket = 1560; + TC_MUTEX_UNLOCK(mutex_formats); + send_MSG_SNDIN_OPEN(pdu, s); + } + s_mark_end(s); + len = s->end - s->data; + if (len > 0) { + ptrdiff_t tres = 0; + //g_hexdump_file("/tmp/taskq_hex_MSG_SNDIN_OPEN.hexdump", s->data, len); + if (chan->mode == 3 || chan->mode == 0) { + SAY("about to call trans_force_write(): (chan->sck_out = %d, len = %d)", chan->sck_out, len); + } + if ((g_interface_type == 0 || g_interface_type == 3) || ((g_interface_type == 1 || g_interface_type == 2) && g_tcp_socket_ok(chan->sck) && g_tcp_can_send(chan->sck, 300))) { + TC_MUTEX_LOCK(mutex_open); + assert(g_open_pending == 0); + g_open_pending++; + TC_MUTEX_UNLOCK(mutex_open); + SAY("about to call trans_force_write(): (chan->sck = %d, chan->sck_out = %d, len = %d)", chan->sck, chan->sck_out, len); + tres = trans_force_write(chan); + if (tres < 0) { + SAY("ERROR: trans_force_write() returned an error code (tres = %d)",tres); + TC_MUTEX_LOCK(mutex_open); + assert(g_open_pending == 1); + g_open_pending--; + TC_MUTEX_UNLOCK(mutex_open); + } + else { + SAY("trans_force_write() returned (tres = %d)",tres); + } + } + else { + SAY("ERROR: unable to send (g_interface_type = %d)", g_interface_type); + } + } + if (pdu != NULL) { + g_free(pdu); + pdu = (MSG_SNDIN_OPEN *)NULL; + } + } + + end:; + if (locked) { + chan->locked = 0; + TC_MUTEX_UNLOCK(chan->lock); + locked = 0; + } + SAY("done."); + return rv; +} + +static int APP_CC handle_finish(struct trans * chan) { + int rv = 0; + + if (chan != NULL) { + unsigned char locked = 0; + if (chan->lock != NULL) { + TC_MUTEX_LOCK(chan->lock); + chan->locked = 1; + locked = 1; + } + trans_detach(chan); + if (locked) { + chan->locked = 0; + TC_MUTEX_UNLOCK(chan->lock); + locked = 0; + } + g_free(chan); + } + g_sleep(200); + TC_MUTEX_LOCK(mutex_done); + g_done = 1; + TC_MUTEX_UNLOCK(mutex_done); + g_sleep(200); + + end:; + return rv; +} + + +static void * APP_CC pa_output_loop(void * arg) { + void * rv = (void *)NULL; + pa_simple * s = (pa_simple *)NULL; + unsigned char done = 0; + unsigned char plocked = 0; + uint8_t sbuf[(MAX_STREAM + 4)]; + uint8_t * sdata = (uint8_t *)(&(sbuf[4])); + uint32_t * slen = (uint32_t *)sbuf; + ptrdiff_t ilen = 0; + stream_list_t litem; + stream_list_t * item = (stream_list_t *)NULL; + + SAY("called"); + + TC_BARR_WAIT(barr_thread); + + return rv; + + pa_disable_sigpipe(); + signal(SIGPIPE, SIG_IGN); + + while (!done) { + *slen = 0; + ilen = 0; + g_memset(&litem,0,sizeof(stream_list_t)); + item = &litem; + if (!plocked) { + TC_MUTEX_LOCK(mutex_pa); + plocked = 1; + } + if (g_pa_count < 1) { + g_pa_waiting++; + TC_COND_WAIT(cond_pa, mutex_pa); + //SAY("awakened: g_pa_count = %d",g_pa_count); + g_pa_waiting--; + } + while (g_pa_count > 0) { + int error = 0; + item = (stream_list_t *)NULL; + //item->s = g_pa_stream; + SQ_DEQ(ilist, &item); + if (item != NULL) { + g_pa_count--; + } + if (item == NULL || item->s == NULL) { + break; + } + ilen = (item->s->end > item->s->data) ? (item->s->end - item->s->data) : 0; + if (ilen > 0) { + *slen += ilen; + g_memcpy(sdata, item->s->data, ilen); + sdata += ilen; + } + //item = (stream_list_t *)NULL; + if (item != NULL && item->s != NULL && item->s->data != NULL) { + free_stream(item->s); + item->s = (struct stream *)NULL; + } + if (item != NULL) { + g_free(item); + item = (stream_list_t *)NULL; + } + } + if (*slen < 1) { + if (plocked) { + TC_MUTEX_UNLOCK(mutex_pa); + plocked = 0; + } + continue; + } + else if (g_pa_trans != NULL && g_pa_trans->sck > -1) { + char * p = (char *)NULL; + unsigned char locked = 0; + struct stream * s = (struct stream *)NULL; + if (g_pa_trans->lock != NULL) { + TC_MUTEX_LOCK(g_pa_trans->lock); + g_pa_trans->locked = 1; + locked = 1; + } + if (plocked) { + TC_MUTEX_UNLOCK(mutex_pa); + plocked = 0; + } + ilen = *slen + 4; + s = trans_get_out_s(g_pa_trans, MAX_STREAM); + p = s->p; + out_uint8a(s, sbuf, ilen); + s_mark_end(s); + SAY("about to send %d bytes to child (g_pfd = %d):",ilen,g_pfd); + { + ptrdiff_t rem = ilen; + int flags = g_pa_trans->send_flags; + g_pa_trans->send_flags |= MSG_NOSIGNAL; + if (1) { + trans_force_write(g_pa_trans); + } + else while (rem > 0) { + ptrdiff_t res = 0; + res = write(g_pa_trans->sck, p, (s->end - p)); + if (res < 0) { + SAY("ERROR: res = %d",res); + break; + } + else { + rem -= res; + } + } + g_pa_trans->send_flags = flags; + } + SAY("sent bytes to child."); + if (locked > 0) { + g_pa_trans->locked = 0; + TC_MUTEX_UNLOCK(g_pa_trans->lock); + locked = 0; + } + } + else if (plocked) { + TC_MUTEX_UNLOCK(mutex_pa); + plocked = 0; + } + TC_MUTEX_LOCK(mutex_done); + done = g_done; + TC_MUTEX_UNLOCK(mutex_done); + } + + end:; + SAY("done."); + TC_THREAD_EXIT(NULL); + return rv; +} + +static int APP_CC sound_get_pulseaudio_server(const char ** server) { + int rv = 0; + glob_t tglob; + char globdir[164]; + g_memset(globdir, 0, sizeof(globdir)); + if (server == NULL) { + rv = -1; + goto end; + } + else { + *server = g_getenv("PULSE_SERVER"); + } + if (*server == NULL) { + uid_t tuid = 0; + unsigned int idx = 0; + g_memset(&tglob,0,sizeof(glob_t)); + pa_get_home_dir(globdir, sizeof(globdir) - 48); + g_strncat(globdir, "/.pulse/*-runtime/native", sizeof(globdir)); + glob(globdir,GLOB_NOSORT,NULL,&tglob); + for (idx = 0; idx < tglob.gl_pathc; idx++) { + int fd = -1; + struct stat finfo; + g_memset(&finfo,0,sizeof(struct stat)); + if (g_strlen(tglob.gl_pathv[idx]) > 0 && stat(tglob.gl_pathv[idx], &finfo) == 0) { + if (S_ISSOCK(finfo.st_mode)) { + *server = g_strndup(tglob.gl_pathv[idx], 164); + break; + } + } + else { + continue; + } + } + globfree(&tglob); + } + + end:; + SAY("DEBUG: *server = \"%s\"",*server); + return rv; +} + +static tbus APP_CC launch_child() { + tbus rv = 0; + tbus fds[2] = { -1, -1 }; + int cpid = 0; + int ppid = 0; + int tpid = 0; + tbus pfd = -1; + tbus cfd = -1; + unsigned char done = 0; + unsigned char locked = 0; + + g_socketpair((int *)fds); + cfd = fds[0]; + pfd = fds[1]; + + ppid = g_getpid(); + + tpid = g_fork(); + if (tpid < 0) { + SAY("ERROR: g_fork() failed"); + } + else if (tpid == 0) { /* child */ + tbus fd_log = -1; + g_is_child = 1; + rv = -1; + cpid = g_getpid(); + //g_tcp_close(pfd); + pfd = -1; + g_pfd = -1; + + launch_pa(&g_pa); + + g_pa_trans = trans_create(WO_LOCAL, MAX_STREAM, MAX_STREAM); + if (g_pa_trans == NULL) { + SAY("ERROR: g_pa_trans is NULL"); + goto end; + } + trans_attach(g_pa_trans, cfd); + g_pa_trans->sck = cfd; + g_tcp_set_non_blocking(g_pa_trans->sck); + if (g_pa_trans != NULL) { + g_pa_trans->trans_data_in = pa_data_in; + g_pa_trans->callback_data = g_pa; + g_pa_trans->header_size = 0; + g_pa_trans->ready = 1; + g_pa_trans->running = 1; + } + + SAY("g_pa_trans = %p, g_pa_trans->sck = %d",g_pa_trans,g_pa_trans->sck); + + pa_disable_sigpipe(); + signal(SIGPIPE, SIG_IGN); + + while (!done) { + tbus objs[8] = {0,0,0,0,0,0,0,0}; + int count = 0; + int timeout = -1; + if (g_pa_trans == NULL) { + SAY("g_pa_trans is NULL"); + continue; + } + else if (g_pa_trans->trans_data_in == NULL) { + SAY("g_pa_trans->trans_data_in is NULL"); + continue; + } + if (trans_get_wait_objs(g_pa_trans, objs, &count, &timeout) != 0) { + SAY("ERROR: trans_get_wait_objs() failed [status = %d]",g_pa_trans->status); + done = 1; + continue; + } + if (count > 0) { + ptrdiff_t i = 0; + unsigned char is_set = 0; + g_obj_wait(objs, count, NULL, 0, timeout); + for (i = 0; i < count; i++) if (g_tcp_socket_ok(objs[i]) && g_is_wait_obj_set(objs[i])) { + is_set = 1; + break; + } + if (is_set) { + if (trans_check_wait_objs(g_pa_trans) < 0) { + SAY("ERROR: trans_check_wait_objs() failed"); + done = 1; + } + } + } + } + + } + else { /* parent */ + unsigned char locked = 0; + pa_disable_sigpipe(); + signal(SIGPIPE, SIG_IGN); + g_is_child = 0; + rv = pfd; + //g_tcp_close(cfd); + g_pa_trans = trans_create(WO_LOCAL, MAX_STREAM, MAX_STREAM); + if (g_pa_trans != NULL && g_pa_trans->lock != NULL) { + TC_MUTEX_LOCK(g_pa_trans->lock); + g_pa_trans->locked = 1; + locked = 1; + } + if (g_pa_trans != NULL) { + trans_attach(g_pa_trans, pfd); + g_pa_trans->sck = pfd; + g_tcp_set_non_blocking(g_pa_trans->sck); + g_pa_trans->trans_data_in = NULL; + g_pa_trans->callback_data = NULL; + g_pa_trans->header_size = 0; + g_pa_trans->ready = 1; + g_pa_trans->running = 1; + } + if (locked > 0) { + g_pa_trans->locked = 0; + TC_MUTEX_UNLOCK(g_pa_trans->lock); + locked = 0; + } + } + + end:; + return rv; +} + +static size_t APP_CC pa_data_in(struct trans * chan) { + size_t rv = 0; + if (chan == NULL) { + SAY("ERROR: chan is NULL"); + } + else { + pa_simple * pa = (pa_simple *)(chan->callback_data); + struct stream * s = (struct stream *)NULL; + s = trans_get_in_s(chan); + trans_force_read(chan, 4); + if (s == NULL) { + SAY("ERROR: input stream is NULL"); + } + else if (pa == NULL) { + SAY("ERROR: pa is NULL"); + } + else { + int error = 0; + uint8_t * ptr = (uint8_t *)NULL; + size_t len = 0; + uint32_t tlen = 0; + in_uint32_le(s, tlen); + len = (size_t)(MIN(tlen,(MAX_STREAM - 4))); + ptr = (uint8_t *)(s->p); + trans_force_read(chan, len); + if (g_fd_log > -1 && len > 0) { + g_file_write(g_fd_log, ptr, len); + } + if ((len > 0) && (pa_simple_write(pa, ptr, len, &error) < 0)) { + SAY("ERROR: pa_simple_write() returned code %d [%s]",error,pa_strerror(error)); + } + else { + rv = len; + } + } + } + end:; + // SAY("done. (rv = %d)",rv); + return rv; +} diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/dynamic/xrdp_rdpeai.h posixrdp/posixxrdp.orig/sesman/dynamic/xrdp_rdpeai.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/dynamic/xrdp_rdpeai.h 1970-01-01 01:00:00.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/dynamic/xrdp_rdpeai.h 2010-11-08 09:56:45.000000000 +0100 @@ -0,0 +1,80 @@ +#if !defined(XRDP_RDPEAI_H) +#define XRDP_RDPEAI_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "defines.h" +#include "arch.h" +#include "crc32.h" +#include "parse.h" +#include "os_calls.h" +#include "rdpdr.h" +#include "rdpdr_methods.h" +#include "stream_list.h" +#include "thread_calls.h" +#include "thread_macros.h" +#include "trans.h" +#include "drdynvc_defs.h" +#include "recording_defs.h" + +#if !defined(SAY) +#define SAY(...) { \ + char cbuf[4096]; \ + g_memset(cbuf,0,sizeof(cbuf)); \ + g_snprintf(cbuf,sizeof(cbuf),__VA_ARGS__); \ + if (0) { g_writeln("[%s() @ line %d]: %s", __func__, __LINE__, cbuf); } \ + g_write_err("[%s() @ line %d]: %s\n", __func__, __LINE__, cbuf); \ +} +#endif + +#if !defined(TC_COND_REINIT) +#define TC_COND_REINIT(x) { \ + tc_t tattr; \ + tc_p pattr = &tattr; \ + g_memset(pattr,0,sizeof(tc_t)); \ + g_memset(x, 0, sizeof(tc_t)); \ + TC_CONDATTR_INIT(pattr); \ + TC_CONDATTR_SETPSHARED(pattr, TC_PROCESS_SHARED); \ + TC_COND_CREATE(x, pattr); \ +} +#endif + +typedef enum rdpeai_interface { + RDPEAI_INET = WO_INET, +#define RDPEAI_INET RDPEAI_INET + RDPEAI_SOCKET = WO_LOCAL, +#define RDPEAI_SOCKET RDPEAI_SOCKET + RDPEAI_FIFO = WO_FIFO +#define RDPEAI_FIFO RDPEAI_FIFO +} rdpeai_interface_t; + +/* { .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 0x0002, .nSamplesPerSec = 0x0000ac44, .nAvgBytesPerSec = 0x0002b110, .nBlockAlign = 0x0004, .wBitsPerSample = 0x0010, .cbSize = 0, .__constructor = NULL, .__destructor = NULL, .data = { } }, */ + +#define RDPEAI_FORMATS_ALL { \ + { .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 0x0002, .nSamplesPerSec = 0x00005622, .nAvgBytesPerSec = 0x00015888, .nBlockAlign = 0x0004, .wBitsPerSample = 0x0010, .cbSize = 0, }, \ + { .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 0x0001, .nSamplesPerSec = 0x00002B11, .nAvgBytesPerSec = 0x0000AC44, .nBlockAlign = 0x0004, .wBitsPerSample = 0x0008, .cbSize = 0, }, \ + { .wFormatTag = WAVE_FORMAT_MULAW, .nChannels = 0x0002, .nSamplesPerSec = 0x00005622, .nAvgBytesPerSec = 0x0000ac44, .nBlockAlign = 0x0002, .wBitsPerSample = 0x0008, .cbSize = 0, }, \ + { .wFormatTag = WAVE_FORMAT_MULAW, .nChannels = 0x0001, .nSamplesPerSec = 0x00002B11, .nAvgBytesPerSec = 0x00005622, .nBlockAlign = 0x0002, .wBitsPerSample = 0x0004, .cbSize = 0, }, \ + { .wFormatTag = WAVE_FORMAT_ALAW, .nChannels = 0x0002, .nSamplesPerSec = 0x00005622, .nAvgBytesPerSec = 0x0000ac44, .nBlockAlign = 0x0002, .wBitsPerSample = 0x0008, .cbSize = 0, }, \ + { .wFormatTag = WAVE_FORMAT_ALAW, .nChannels = 0x0001, .nSamplesPerSec = 0x00002B11, .nAvgBytesPerSec = 0x00005622, .nBlockAlign = 0x0002, .wBitsPerSample = 0x0004, .cbSize = 0, }, \ +} + +#define RDPEAI_FORMATS_DEFAULT { \ + { .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 0x0002, .nSamplesPerSec = 0x00005622, .nAvgBytesPerSec = 0x00015888, .nBlockAlign = 0x0004, .wBitsPerSample = 0x0010, .cbSize = 0, }, \ + { .wFormatTag = WAVE_FORMAT_MULAW, .nChannels = 0x0002, .nSamplesPerSec = 0x00005622, .nAvgBytesPerSec = 0x0000ac44, .nBlockAlign = 0x0002, .wBitsPerSample = 0x0008, .cbSize = 0, }, \ +} + +/* #define RDPEAI_NUM_FORMATS (sizeof(rdpeai_audio_formats) / sizeof(AUDIO_FORMAT_REC)) */ +#define RDPEAI_NUM_FORMATS 2 + +#endif diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/libscp/libscp_init.c posixrdp/posixxrdp.orig/sesman/libscp/libscp_init.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/libscp/libscp_init.c 2010-11-02 11:51:10.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/libscp/libscp_init.c 2010-11-08 09:56:45.000000000 +0100 @@ -42,6 +42,8 @@ scp_lock_init(); + log_message(s_log, LOG_LEVEL_WARNING, "[init:%d] libscp initialized", __LINE__); + return 0; } diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/libscp/libscp_session.c posixrdp/posixxrdp.orig/sesman/libscp/libscp_session.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/libscp/libscp_session.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/libscp/libscp_session.c 2010-11-08 09:56:45.000000000 +0100 @@ -27,10 +27,13 @@ #include "libscp_session.h" +#include +#include #include -#include #include +#include "dbg.h" + extern struct log_config* s_log; /*******************************************************************/ @@ -39,6 +42,8 @@ { struct SCP_SESSION* s; + MDBGLOG("libscp","[scp_session_create()]"); + s = (struct SCP_SESSION*)g_malloc(sizeof(struct SCP_SESSION), 1); if (0 == s) { @@ -52,6 +57,8 @@ int scp_session_set_type(struct SCP_SESSION* s, tui8 type) { + MDBGLOG("libscp","[scp_session_set_type()]"); + switch (type) { case SCP_SESSION_TYPE_XVNC: @@ -66,11 +73,13 @@ if (NULL == s->mng) { log_message(s_log, LOG_LEVEL_ERROR, "[session:%d] set_type: internal error", __LINE__); + MDBGLOG("libscp"," ^^^ (scp_session_set_type) [session:%d] internal error, returning", __LINE__); return 1; } break; default: log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_type: unknown type", __LINE__); + MDBGLOG("libscp", " ^^^ (scp_session_set_type) [session:%d] unknown type", __LINE__); return 1; } return 0; @@ -121,6 +130,7 @@ case 15: case 16: case 24: + case 32: s->bpp = bpp; default: return 1; @@ -165,6 +175,7 @@ if (0 == str) { log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_username: null username", __LINE__); + MDBGLOG("libscp","[scp_session_set_username()] (session:%d) null username",__LINE__); return 1; } if (0 != s->username) @@ -187,6 +198,7 @@ if (0 == str) { log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_password: null password", __LINE__); + MDBGLOG("libscp","[scp_session_set_password()] (session:%d) null password",__LINE__); return 1; } if (0 != s->password) @@ -335,9 +347,10 @@ case SCP_ADDRESS_TYPE_IPV4: /* convert from char to 32bit*/ ret = inet_pton(AF_INET, addr, &ip4); - if (0 == ret) + if (ret == 0) { log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_addr: invalid address", __LINE__); + MDBGLOG("libscp","[session:%d] set_addr: invalid address\0", __LINE__); inet_pton(AF_INET, "127.0.0.1", &ip4); g_memcpy(&(s->ipv4addr), &(ip4.s_addr), 4); return 1; @@ -351,9 +364,10 @@ case SCP_ADDRESS_TYPE_IPV6: /* convert from char to 128bit*/ ret = inet_pton(AF_INET6, addr, &ip6); - if (0 == ret) + if (ret == 0) { log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_addr: invalid address", __LINE__); + MDBGLOG("libscp","[session:%d] set_addr: invalid address\0", __LINE__); inet_pton(AF_INET, "::1", &ip6); g_memcpy(s->ipv6addr, &(ip6.s6_addr), 16); return 1; diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/libscp/libscp_tcp.c posixrdp/posixxrdp.orig/sesman/libscp/libscp_tcp.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/libscp/libscp_tcp.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/libscp/libscp_tcp.c 2010-11-08 09:56:45.000000000 +0100 @@ -27,11 +27,16 @@ #include "libscp_tcp.h" +#include +#include #include -#include #include #include #include +#include + +#include "os_calls.h" +#include "dbg.h" extern struct log_config* s_log; @@ -120,15 +125,111 @@ } /*****************************************************************************/ -int DEFAULT_CC -scp_tcp_bind(int sck, char* addr, char* port) +static int DEFAULT_CC +old_scp_tcp_bind(int sck, char* addr, char* port) { - struct sockaddr_in s; +// struct sockaddr_storage sp; +// struct sockaddr_in6 *s = NULL; - memset(&s, 0, sizeof(struct sockaddr_in)); - s.sin_family = AF_INET; - s.sin_port = htons(atoi(port)); - s.sin_addr.s_addr = inet_addr(addr); - return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in)); +// memset(s, 0, sizeof(struct sockaddr_storage)); +// s.sin6_family = AF_INET6; +// s.sin6_port = htons(atoi(port)); + //s.sin_addr.s_addr = inet_addr(addr); +// return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in)); + return 0; +} + +/*****************************************************************************/ +int DEFAULT_CC +old2_scp_tcp_bind(int sck, char* addr, char* port) { + int res = 0; + struct in6_addr any6addr = IN6ADDR_ANY_INIT; + struct sockaddr_storage sp; + struct sockaddr_in6 * s = (struct sockaddr_in6 *)NULL; + char tbuf[256]; + + g_snprintf(tbuf,511,"[libscp]->scp_tcp_bind() called: sck = %d; addr = %s; port = %s\0",sck,addr,port); + DBGLOG("net",tbuf); + + s = (struct sockaddr_in6 *)&sp; + memset(s, 0, sizeof(struct sockaddr_storage)); + s->sin6_family = AF_INET6; + s->sin6_port = htons((tui16)atoi(port)); + s->sin6_flowinfo = 0; + //s->sin6_addr = in6addr_any; + s->sin6_addr = any6addr; + res = bind(sck, (struct sockaddr *)s, sizeof(*s)); + g_snprintf(tbuf,255," ** scp_tcp_bind(): res = %d\0",res); + DBGLOG("net",tbuf); + return res; } + +/*****************************************************************************/ +int DEFAULT_CC +scp_tcp_bind_flags(int sck, char* addr, char* port, int flags) { + int res = -1; + int error = 0; +#ifdef _XRDP_ENABLE_IPv6_ + int ipv4count = 0; +#endif + char * service = (char *)NULL; + struct addrinfo hints; + struct addrinfo * i = (struct addrinfo *)NULL; + struct addrinfo * j = (struct addrinfo *)NULL; + + /* initialize (zero out) local variables: */ + g_memset(&hints, 0, sizeof(hints)); + + hints.ai_family = AF_UNSPEC; + hints.ai_flags = flags; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + error = getaddrinfo(addr,port,&hints,&i); + if (error) { + MDBGLOG("libscp","[scp_tcp_bind()] ERROR: %d\0",error); + res = -1; + } + else { + /* iterate the entire list returned by getaddrinfo() + * and determine how many IPv6 and IPv4 addresses, respectively, + * are available: + */ + j = i; +#ifdef _XRDP_ENABLE_IPv6_ + while ((j != NULL) && (res < 0)) { + if (j->ai_family == PF_INET6) { + res = bind(sck, (struct sockaddr *)j->ai_addr, j->ai_addrlen); + } + else { + ipv4count++; + } + j = j->ai_next; + } + if ((res < 0) && (ipv4count > 0)) { + j = i; + while ((j != NULL) && (res < 0)) { + res = bind(sck, (struct sockaddr *)j->ai_addr, j->ai_addrlen); + j = j->ai_next; + } + } +#else + while ((j != NULL) && (res < 0)) { + res = bind(sck, (struct sockaddr *)j->ai_addr, j->ai_addrlen); + j = j->ai_next; + } +#endif + } + + return res; +} + + +/*****************************************************************************/ +int DEFAULT_CC +scp_tcp_bind(int sck, char* addr, char* port) { + int flags = 0; + //flags = AI_PASSIVE | AI_ADDRCONFIG; + flags = AI_ADDRCONFIG; + return scp_tcp_bind_flags(sck, addr, port, flags); +} diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/libscp/libscp_tcp.h posixrdp/posixxrdp.orig/sesman/libscp/libscp_tcp.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/libscp/libscp_tcp.h 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/libscp/libscp_tcp.h 2010-11-08 09:56:45.000000000 +0100 @@ -60,6 +60,19 @@ * @param sck Listening socket * @param addr Listening address * @param port Listening port + * @param flags getaddrinfo() hint flags + * @return 0 on success, -1 on error + * + */ +int DEFAULT_CC +scp_tcp_bind_flags(int sck, char* addr, char* port, int flags); + +/** + * + * @brief Binds the listening socket + * @param sck Listening socket + * @param addr Listening address + * @param port Listening port * @return 0 on success, -1 on error * */ diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/libscp/libscp_v1s.c posixrdp/posixxrdp.orig/sesman/libscp/libscp_v1s.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/libscp/libscp_v1s.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/libscp/libscp_v1s.c 2010-11-08 09:56:45.000000000 +0100 @@ -61,6 +61,10 @@ return SCP_SERVER_STATE_NETWORK_ERR; } } + else + { + version = 1; + } in_uint32_be(c->in_s, size); if (size < 12) @@ -238,6 +242,8 @@ /* send password request */ version=1; + size=12; + cmdset=0; cmd=3; out_uint32_be(c->out_s, version); /* version */ diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/libscp/Makefile.am posixrdp/posixxrdp.orig/sesman/libscp/Makefile.am --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/libscp/Makefile.am 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/libscp/Makefile.am 2010-11-08 09:56:45.000000000 +0100 @@ -1,9 +1,17 @@ AM_CFLAGS = \ + -pthread \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ -DXRDP_SBIN_PATH=\"${sbindir}\" \ -DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \ - -DXRDP_PID_PATH=\"${localstatedir}/run\" + -DXRDP_PID_PATH=\"${localstatedir}/run\" \ + -D_FILE_OFFSET_BITS=64 \ + -D_REENTRANT \ + -D_GNU_SOURCE \ + -D_XOPEN_SOURCE_EXTENDED + +AM_LDFLAGS = \ + -lpthread INCLUDES = \ -I$(top_srcdir)/common @@ -25,4 +33,4 @@ libscp_vX.c libscp_la_LIBADD = \ - $(top_srcdir)/common/libcommon.la + $(top_builddir)/common/libcommon.la diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/lock.c posixrdp/posixxrdp.orig/sesman/lock.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/lock.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/lock.c 2010-11-08 09:56:45.000000000 +0100 @@ -25,10 +25,10 @@ extern struct config_sesman* g_cfg; /* in sesman.c */ -static tbus g_sync_mutex = 0; -static tbus g_lock_chain = 0; -static tbus g_sync_sem = 0; -static tbus g_lock_socket = 0; +static tc_p g_sync_mutex = 0; +static tc_p g_lock_chain = 0; +static tc_p g_sync_sem = 0; +static tc_p g_lock_socket = 0; /******************************************************************************/ void APP_CC diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/Makefile.am posixrdp/posixxrdp.orig/sesman/Makefile.am --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/Makefile.am 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/Makefile.am 2010-11-08 09:56:45.000000000 +0100 @@ -1,9 +1,19 @@ AM_CFLAGS = \ + -pthread \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ -DXRDP_SBIN_PATH=\"${sbindir}\" \ -DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \ - -DXRDP_PID_PATH=\"${localstatedir}/run\" + -DXRDP_PID_PATH=\"${localstatedir}/run\" \ + -D_FILE_OFFSET_BITS=64 \ + -D_REENTRANT \ + -D_GNU_SOURCE \ + -D_XOPEN_SOURCE_EXTENDED \ + -D_POSIX_PTHREAD_SEMANTICS \ + -D_POSIX_PTHREADS + +LDFLAGS = \ + -lpthread INCLUDES = \ -I$(top_srcdir)/common \ @@ -46,8 +56,8 @@ $(AUTH_C) xrdp_sesman_LDADD = \ - $(top_srcdir)/common/libcommon.la \ - $(top_srcdir)/sesman/libscp/libscp.la \ + $(top_builddir)/common/libcommon.la \ + $(top_builddir)/sesman/libscp/libscp.la \ $(AUTH_LIB) sesmansysconfdir=$(sysconfdir)/xrdp @@ -58,9 +68,9 @@ SUBDIRS = \ libscp \ - tools \ sessvc \ - chansrv + chansrv \ + dynamic # must be tab below install-data-hook: diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/scp_v0.c posixrdp/posixxrdp.orig/sesman/scp_v0.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/scp_v0.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/scp_v0.c 2010-11-08 09:56:45.000000000 +0100 @@ -77,6 +77,7 @@ if (display == 0) { auth_end(data); + data = 0; scp_v0s_deny_connection(c); } else diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/scp_v1.c posixrdp/posixxrdp.orig/sesman/scp_v1.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/scp_v1.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/scp_v1.c 2010-11-08 09:56:45.000000000 +0100 @@ -29,6 +29,7 @@ //#include "libscp_types.h" #include "libscp.h" +#include "dbg.h" extern struct config_sesman* g_cfg; /* in sesman.c */ @@ -48,6 +49,8 @@ int scount; SCP_SID sid; + MDBGLOG("sesman","scp_v1_process() called"); + retries = g_cfg->sec.login_retry; current_try = retries; @@ -186,6 +189,8 @@ static void parseCommonStates(enum SCP_SERVER_STATES_E e, char* f) { + MDBGLOG("sesman","parseCommonStates() called"); + switch (e) { case SCP_SERVER_STATE_VERSION_ERR: diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/scp_v1_mng.c posixrdp/posixxrdp.orig/sesman/scp_v1_mng.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/scp_v1_mng.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/scp_v1_mng.c 2010-11-08 09:56:45.000000000 +0100 @@ -38,11 +38,16 @@ scp_v1_mng_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) { long data; + int retries; + int current_try; enum SCP_SERVER_STATES_E e; struct SCP_DISCONNECTED_SESSION* slist = 0; int scount; int end = 0; + retries = g_cfg->sec.login_retry; + current_try = retries; + data = auth_userpass(s->username, s->password); /*LOG_DBG("user: %s\npass: %s", s->username, s->password);*/ diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/sesman.c posixrdp/posixxrdp.orig/sesman/sesman.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/sesman.c 2010-11-02 11:51:10.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/sesman.c 2010-11-08 09:56:45.000000000 +0100 @@ -25,7 +25,9 @@ * */ +#include #include "sesman.h" +#include "dbg.h" int g_sck; int g_pid; @@ -52,12 +54,16 @@ int cont; tbus sck_obj; tbus robjs[8]; + char tbuf[512]; /*main program loop*/ log_message(&(g_cfg->log), LOG_LEVEL_INFO, "listening..."); + g_snprintf(tbuf,511,"[%s()]: listening... (address = %s; port = %s)",__func__,g_cfg->listen_address, g_cfg->listen_port); + //snprintf(tbuf,511," ^^^ listen_address = %s; listen_port = %s\0",g_cfg->listen_address,g_cfg->listen_port); + DBGLOG("sesman",tbuf); g_sck = g_tcp_socket(); g_tcp_set_non_blocking(g_sck); - error = scp_tcp_bind(g_sck, g_cfg->listen_address, g_cfg->listen_port); + error = scp_tcp_bind_flags(g_sck, g_cfg->listen_address, g_cfg->listen_port, AI_ADDRCONFIG | AI_PASSIVE); if (error == 0) { error = g_tcp_listen(g_sck); @@ -87,23 +93,25 @@ g_reset_wait_obj(g_sync_event); session_sync_start(); } - if (g_is_wait_obj_set(sck_obj)) /* incomming connection */ - { - in_sck = g_tcp_accept(g_sck); - if ((in_sck == -1) && g_tcp_last_error_would_block(g_sck)) - { - /* should not get here */ - g_sleep(100); - } - else if (in_sck == -1) - { - /* error, should not get here */ - break; - } + if (g_is_wait_obj_set(sck_obj)) /* incoming connection */ + { + MDBGLOG("sesman","sesman_main_loop(): incoming connection!"); + in_sck = g_tcp_accept(g_sck); + if ((in_sck == -1) && g_tcp_last_error_would_block(g_sck)) + { + /* should not get here */ + g_sleep(100); + } + else if (in_sck == -1) + { + /* error, should not get here */ + break; + } else { /* we've got a connection, so we pass it to scp code */ LOG_DBG(&(g_cfg->log), "new connection"); + DBGLOG("sesman","[xdrp-sesman]->sesman_main_loop(): new connection"); thread_scp_start(in_sck); /* todo, do we have to wait here ? */ } @@ -115,15 +123,19 @@ { log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "listen error %d (%s)", g_get_errno(), g_get_strerror()); + snprintf(tbuf,511,"[xdrp-sesman]->sesman_main_loop(): listen error %d (%s)\0",g_get_errno(), g_get_strerror()); + DBGLOG("sesman",tbuf); } } - else - { + else { log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "bind error on " "port '%s': %d (%s)", g_cfg->listen_port, g_get_errno(), g_get_strerror()); + snprintf(tbuf,511,"[xdrp-sesman]->sesman_main_loop(): bind error on port '%s': %d (%s)\0",g_cfg->listen_port,g_get_errno(), g_get_strerror()); + DBGLOG("sesman",tbuf); } g_tcp_close(g_sck); + DBGLOG("sesman","[xdrp-sesman]->sesman_main_loop(): done."); } /******************************************************************************/ @@ -137,12 +149,13 @@ char pid_s[8]; char text[256]; char pid_file[256]; + char tbuf[512]; g_snprintf(pid_file, 255, "%s/xrdp-sesman.pid", XRDP_PID_PATH); if (1 == argc) { /* no options on command line. normal startup */ - /* g_printf("starting sesman...\n"); */ + g_printf("starting sesman...\n"); daemon = 1; } else if ((2 == argc) && ((0 == g_strcasecmp(argv[1], "--nodaemon")) || @@ -318,6 +331,9 @@ /* start program main loop */ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "starting sesman with pid %d", g_pid); + snprintf(tbuf,511,"[xdrp-sesman]->main(): starting sesman with pid = %d\0",g_pid); + DBGLOG("sesman",tbuf); + /* make sure the /tmp/.X11-unix directory exist */ if (!g_directory_exist("/tmp/.X11-unix")) @@ -347,6 +363,7 @@ log_end(&(g_cfg->log)); } + DBGLOG("sesman","[xdrp-sesman]->main(): done."); return 0; } diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/sesman.ini posixrdp/posixxrdp.orig/sesman/sesman.ini --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/sesman.ini 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/sesman.ini 2010-11-08 09:56:45.000000000 +0100 @@ -1,5 +1,5 @@ [Globals] -ListenAddress=127.0.0.1 +ListenAddress=:: ListenPort=3350 EnableUserWindowManager=1 UserWindowManager=startwm.sh @@ -20,7 +20,7 @@ [Logging] LogFile=/var/log/xrdp-sesman.log LogLevel=DEBUG -EnableSyslog=0 +EnableSyslog=1 SyslogLevel=DEBUG [X11rdp] @@ -28,9 +28,13 @@ param2=-ac param3=-nolisten param4=tcp +;param5=-depth +;param6=32 [Xvnc] param1=-bs param2=-ac param3=-nolisten param4=tcp +param5=-SecurityTypes +param6=None diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/session.c posixrdp/posixxrdp.orig/sesman/session.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/session.c 2010-11-02 11:51:10.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/session.c 2010-11-08 09:56:45.000000000 +0100 @@ -27,6 +27,7 @@ #include "sesman.h" #include "libscp_types.h" +#include "dbg.h" #include //#include @@ -55,19 +56,6 @@ { struct session_chain* tmp; - /* convert from SCP_SESSION_TYPE namespace to SESMAN_SESSION_TYPE namespace */ - switch (type) - { - case SCP_SESSION_TYPE_XVNC: - type = SESMAN_SESSION_TYPE_XVNC; - break; - case SCP_SESSION_TYPE_XRDP: - type = SESMAN_SESSION_TYPE_XRDP; - break; - default: - return 0; - } - /*THREAD-FIX require chain lock */ lock_chain_acquire(); @@ -166,20 +154,31 @@ /******************************************************************************/ static void DEFAULT_CC -session_start_sessvc(int xpid, int wmpid, long data) +session_start_sessvc(int xpid, int wmpid, long data, char * uname, char * audio_fifo_path) { - struct list* sessvc_params; + struct list * sessvc_params = (struct list *)NULL; char wmpid_str[25]; char xpid_str[25]; + char uname_str[100]; + char audio_str[256]; char exe_path[262]; - int i; + int i = 0; + + /* initialize (zero out) local variables: */ + g_memset(wmpid_str,0,sizeof(char) * 25); + g_memset(xpid_str,0,sizeof(char) * 25); + g_memset(exe_path,0,sizeof(char) * 262); + g_memset(uname_str,0,sizeof(char) * 100); + g_memset(audio_str,0,sizeof(char) * 256); /* new style waiting for clients */ - g_sprintf(wmpid_str, "%d", wmpid); - g_sprintf(xpid_str, "%d", xpid); + g_snprintf(wmpid_str, 24, "%d", wmpid); + g_snprintf(xpid_str, 24, "%d", xpid); + g_snprintf(uname_str, 99, "%s", uname); + g_snprintf(audio_str, 255, "%s", audio_fifo_path); log_message(&(g_cfg->log), LOG_LEVEL_INFO, - "starting xrdp-sessvc - xpid=%s - wmpid=%s", - xpid_str, wmpid_str); + "starting xrdp-sessvc - xpid=%s - wmpid=%s - uname=%s - audio_fifo_path=%s", + xpid_str, wmpid_str, uname_str, audio_str); sessvc_params = list_create(); sessvc_params->auto_free = 1; @@ -190,6 +189,8 @@ list_add_item(sessvc_params, (long)g_strdup(exe_path)); list_add_item(sessvc_params, (long)g_strdup(xpid_str)); list_add_item(sessvc_params, (long)g_strdup(wmpid_str)); + list_add_item(sessvc_params, (long)g_strdup(uname_str)); + list_add_item(sessvc_params, (long)g_strdup(audio_str)); list_add_item(sessvc_params, 0); /* mandatory */ /* executing sessvc */ @@ -197,8 +198,8 @@ /* should not get here */ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, - "error starting xrdp-sessvc - pid %d - xpid=%s - wmpid=%s", - g_getpid(), xpid_str, wmpid_str); + "error starting xrdp-sessvc - pid %d - xpid=%s - wmpid=%s - uname=%s - audio_fifo_path=%s", + g_getpid(), xpid_str, wmpid_str, uname_str, audio_str); /* logging parameters */ /* no problem calling strerror for thread safety: other threads @@ -300,22 +301,32 @@ char* password, tbus data, tui8 type, char* domain, char* program, char* directory) { - int display; - int pid; - int wmpid; - int xpid; - int i; + int display = 0; + int pid = 0; + int wmpid = 0; + int xpid = 0; + int i = 0; char geometry[32]; char depth[32]; char screen[32]; char text[256]; char passwd_file[256]; - char** pp1; - struct session_chain* temp; - struct list* xserver_params=0; + char ** pp1 = (char **)NULL; + char * audio_fifo_path = (char *)NULL; + struct session_chain * temp = (struct session_chain *)NULL; + struct list * xserver_params = (struct list *)NULL; time_t ltime; struct tm stime; + /* initialize (zero out) local variables: */ + g_memset(<ime,0,sizeof(time_t)); + g_memset(&stime,0,sizeof(struct tm)); + g_memset(geometry,0,sizeof(char) * 32); + g_memset(depth,0,sizeof(char) * 32); + g_memset(screen,0,sizeof(char) * 32); + g_memset(text,0,sizeof(char) * 256); + g_memset(passwd_file,0,sizeof(char) * 256); + /* check to limit concurrent sessions */ if (g_session_count >= g_cfg->sess.max_sessions) { @@ -346,6 +357,7 @@ g_free(temp); return 0; } + wmpid = 0; pid = g_fork(); if (pid == -1) { @@ -527,7 +539,14 @@ g_snprintf(text, 255, ":%d.0", display); g_setenv("DISPLAY", text, 1); /* new style waiting for clients */ - session_start_sessvc(xpid, wmpid, data); + g_snprintf(text, 255, "%s", username); + g_setenv("USER", text, 1); + g_snprintf(text, 255, "/home/%s", username); + g_setenv("HOME", text, 1); + g_snprintf(text, 255, "/tmp/xrdp_audio_%d_fifo", wmpid); + g_setenv("XRDP_AUDIO_FIFO", text, 1); + audio_fifo_path = g_strdup(text); + session_start_sessvc(xpid, wmpid, data, username, audio_fifo_path); } } } diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/sessvc/Makefile.am posixrdp/posixxrdp.orig/sesman/sessvc/Makefile.am --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/sessvc/Makefile.am 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/sessvc/Makefile.am 2010-11-08 09:56:45.000000000 +0100 @@ -1,9 +1,17 @@ AM_CFLAGS = \ + -pthread \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ -DXRDP_SBIN_PATH=\"${sbindir}\" \ -DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \ - -DXRDP_PID_PATH=\"${localstatedir}/run\" + -DXRDP_PID_PATH=\"${localstatedir}/run\" \ + -D_FILE_OFFSET_BITS=64 \ + -D_REENTRANT \ + -D_GNU_SOURCE \ + -D_XOPEN_SOURCE_EXTENDED + +AM_LDFLAGS = \ + -lpthread INCLUDES = \ -I$(top_srcdir)/common @@ -15,4 +23,4 @@ sessvc.c xrdp_sessvc_LDADD = \ - $(top_srcdir)/common/libcommon.la + $(top_builddir)/common/libcommon.la diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/sessvc/sessvc.c posixrdp/posixxrdp.orig/sesman/sessvc/sessvc.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/sessvc/sessvc.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/sessvc/sessvc.c 2010-11-08 09:56:45.000000000 +0100 @@ -25,12 +25,23 @@ * */ +#include +#include +#include +#include +#include +#include +#include +#include #if defined(HAVE_CONFIG_H) #include "config_ac.h" #endif #include "file_loc.h" #include "os_calls.h" #include "arch.h" +#include "dbg.h" + + static int g_term = 0; @@ -73,16 +84,31 @@ int DEFAULT_CC main(int argc, char** argv) { - int ret; - int chansrv_pid; - int wm_pid; - int x_pid; - int lerror; + int ret = 0; + int sessvc_pid = 0; + int chansrv_pid = 0; + int wm_pid = 0; + int x_pid = 0; + int lerror = 0; + int fd_username = -1; + int lckres = 0; + int lexists = 0; + char username[100]; + char audio_fifo_path[256]; + char fd_userfile[256]; char exe_path[262]; + struct flock fl = { F_WRLCK, SEEK_SET, 0, 0, 0 }; + + g_memset(username,0,sizeof(username)); + g_memset(audio_fifo_path,0,sizeof(audio_fifo_path)); + g_memset(fd_userfile,0,sizeof(fd_userfile)); + g_memset(exe_path,0,sizeof(exe_path)); + + sessvc_pid = g_getpid(); if (argc < 3) { - g_writeln("xrdp-sessvc: exiting, not enough params"); + g_writeln("xrdp-sessvc: exiting, not enough parameters"); return 1; } g_signal_kill(term_signal_handler); /* SIGKILL */ @@ -93,8 +119,52 @@ wm_pid = g_atoi(argv[2]); g_writeln("xrdp-sessvc: waiting for X (pid %d) and WM (pid %d)", x_pid, wm_pid); + + fl.l_type = F_WRLCK; + fl.l_type = F_UNLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_pid = sessvc_pid; + /* run xrdp-chansrv as a seperate process */ + chansrv_pid = g_fork(); + + if ((chansrv_pid > 0) && (chansrv_pid != sessvc_pid)) { + struct passwd * pw = (struct passwd *)NULL; + uid_t tuid = 0; + gid_t tgid = 0; + if (argc > 3 && argv[3] != NULL) { + g_snprintf(username,99,"%s",argv[3]); + } + else { + g_snprintf(username,99,"%s",g_getenv("USER")); + } + pw = getpwnam((const char *)username); + tuid = pw->pw_uid; + tgid = pw->pw_gid; + setgid(tgid); + setuid(tuid); + if (argc > 4 && argv[4] != NULL) { + g_snprintf(audio_fifo_path,255,"%s",argv[4]); + } + else { + g_snprintf(audio_fifo_path,255,"%s",g_getenv("XRDP_AUDIO_FIFO")); + } + g_snprintf(fd_userfile,255,CHANSRV_USERNAME_PATH,chansrv_pid); + lexists = g_file_exist(fd_userfile); + if (lexists < 1) { + fd_username = g_file_open(fd_userfile); + } + if ((lexists < 1) && (fd_username > -1)) { + lckres = g_file_lock(fd_username,0,0); /* lock the file for writing */ + if (lckres > 0) { + g_file_write(fd_username,username,g_strlen(username)); + } + g_file_close(fd_username); + } + } if (chansrv_pid == -1) { g_writeln("xrdp-sessvc: fork error"); @@ -106,7 +176,7 @@ g_snprintf(exe_path, 261, "%s/xrdp-chansrv", XRDP_SBIN_PATH); g_execlp3(exe_path, "xrdp-chansrv", 0); /* should not get here */ - g_writeln("xrdp-sessvc: g_execvp failed"); + g_writeln("xrdp-sessvc: g_execlp3() failed"); return 1; } lerror = 0; @@ -115,6 +185,7 @@ while ((ret == 0) && !g_term) { ret = g_waitpid(wm_pid); + g_sleep(1); } if (ret < 0) { @@ -129,6 +200,7 @@ while ((ret == 0) && !g_term) { ret = g_waitpid(chansrv_pid); + g_sleep(1); } chansrv_cleanup(chansrv_pid); /* kill X server */ @@ -138,6 +210,10 @@ while ((ret == 0) && !g_term) { ret = g_waitpid(x_pid); + g_sleep(1); + } + if (chansrv_pid > 0 && fd_userfile != NULL && g_strlen(fd_userfile) > 0) { + unlink(fd_userfile); } g_writeln("xrdp-sessvc: clean exit"); return 0; diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/startwm.sh posixrdp/posixxrdp.orig/sesman/startwm.sh --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/startwm.sh 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/startwm.sh 2010-11-08 09:56:45.000000000 +0100 @@ -3,7 +3,7 @@ # change the order in line below to run to run whatever window manager you # want, default to kde -SESSIONS="startkde gnome-session startxfce4 xterm" +SESSIONS="startxfce4 gnome-session startkde wmaker fvwm2 xterm" # change PATH to be what your environment needs usually what is in # /etc/environment @@ -23,15 +23,57 @@ #. /etc/profile -for WindowManager in $SESSIONS +# return value: (default to error code 1) +RV=1 + +if [ -z "${AUDIO_FIFO_PATH}" -o ! \( -p "${AUDIO_FIFO_PATH}" \) ]; then + unset AUDIO_FIFO_PATH +fi +unset PA_MODNUM + +PA_NATIVE=1 +## PulseAudio: +if [ ${PA_NATIVE} -eq 0 ]; then +if [ -f /usr/bin/pactl ]; then + if [ -f /usr/bin/mkfifo ]; then + export AUDIO_FIFO_PATH="/tmp/xrdp_audio_${$}_fifo" + if [ -z "${AUDIO_FIFO_PATH}" -o ! \( -p "${AUDIO_FIFO_PATH}" \) ]; then + if [ -p "${AUDIO_FIFO_PATH}" ]; then + rm ${AUDIO_FIFO_PATH} + fi + /usr/bin/mkfifo ${AUDIO_FIFO_PATH} + /bin/chmod 0666 ${AUDIO_FIFO_PATH} + fi + PA_MODNUM=$(/usr/bin/pactl load-module module-pipe-sink file=$AUDIO_FIFO_PATH sink_name=xrdp_$$) + ## echo $PA_MODNUM > /tmp/a + +/usr/bin/pacmd <rsr=0; - g_strncpy(s->locale,"it_IT 0123456789",18); + g_strncpy(s->locale,"en_US 0123456789",18); return 0; } diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/tools/tcp.c posixrdp/posixxrdp.orig/sesman/tools/tcp.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/tools/tcp.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/tools/tcp.c 2010-11-08 09:56:45.000000000 +0100 @@ -27,12 +27,17 @@ #include "sesman.h" +#include +#include #include -#include +#include #include #include #include +#include "os_calls.h" +#include "dbg.h" + /*****************************************************************************/ int DEFAULT_CC tcp_force_recv(int sck, char* data, int len) @@ -133,13 +138,100 @@ /*****************************************************************************/ int DEFAULT_CC +old_tcp_bind(int sck, char* addr, char* port) +{ + int res = 0; + struct in6_addr any6addr = IN6ADDR_ANY_INIT; + struct sockaddr_storage sp; + struct sockaddr_in6 * s = (struct sockaddr_in6 *)NULL; + char tbuf[512]; + + snprintf(tbuf,511,"[tools/tcp]->tcp_bind() called: sck = %d; addr = %s; port = %s\0",sck,addr,port); + DBGLOG("net",tbuf); + s = (struct sockaddr_in6 *)&sp; + memset(s, 0, sizeof(struct sockaddr_storage)); + s->sin6_family = AF_INET6; + s->sin6_port = htons((tui16)atoi(port)); + s->sin6_flowinfo = 0; + //s->sin6_addr = in6addr_any; + s->sin6_addr = any6addr; + res = bind(sck, (struct sockaddr *)s, sizeof(*s)); + snprintf(tbuf,255," ** tcp_bind(): res = %d\0",res); + DBGLOG("net",tbuf); + return res; +} + + +/*****************************************************************************/ +int DEFAULT_CC +tcp_bind_flags(int sck, char* addr, char* port, int flags) +{ + int res = -1; + int error = 0; +#ifdef _XRDP_ENABLE_IPv6_ + int ipv4count = 0; +#endif + char * service = (char *)NULL; + struct addrinfo hints; + struct addrinfo * i = (struct addrinfo *)NULL; + struct addrinfo * j = (struct addrinfo *)NULL; + + /* initialize (zero out) local variables: */ + g_memset(&hints, 0, sizeof(hints)); + + hints.ai_family = AF_UNSPEC; + hints.ai_flags = flags; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + error = getaddrinfo(addr,port,&hints,&i); + if (error) { + res = -1; + } + else { + /* iterate the entire list returned by getaddrinfo() + * and determine how many IPv6 and IPv4 addresses, respectively, + * are available: + */ + j = i; +#ifdef _XRDP_ENABLE_IPv6_ + while (j && (res < 0)) { + if (j->ai_family == PF_INET6) { + res = bind(sck, j->ai_addr, j->ai_addrlen); + } + else { + ipv4count++; + } + j = j->ai_next; + } + if ((res < 0) && (ipv4count > 0)) { + j = i; + while (j && (res < 0)) { + if (j->ai_family != PF_INET6) { + res = bind(sck, j->ai_addr, j->ai_addrlen); + } + } + j = j->ai_next; + } +#else + while (j && (res < 0)) { + res = bind(sck, j->ai_addr, j->ai_addrlen); + j = j->ai_next; + } +#endif + } + + return res; +} + + +/*****************************************************************************/ +int DEFAULT_CC tcp_bind(int sck, char* addr, char* port) { - struct sockaddr_in s; + int flags = 0; + + MDBGLOG("net","[tools/tcp]->tcp_bind() called: sck = %d; addr = %s; port = %s\0",sck,addr,port); - memset(&s, 0, sizeof(struct sockaddr_in)); - s.sin_family = AF_INET; - s.sin_port = htons(atoi(port)); - s.sin_addr.s_addr = inet_addr(addr); - return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in)); + flags = AI_ADDRCONFIG | AI_PASSIVE; + return tcp_bind_flags(sck, addr, port, flags); } diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/tools/tcp.h posixrdp/posixxrdp.orig/sesman/tools/tcp.h --- xrdp/xrdp-0.5.0~20100303cvs.orig/sesman/tools/tcp.h 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/sesman/tools/tcp.h 2010-11-08 09:56:45.000000000 +0100 @@ -58,6 +58,19 @@ * @param sck Listening socket * @param addr Listening address * @param port Listening port + * @param flags getaddrinfo() hint flags + * @return 0 on success, -1 on error + * + */ +int DEFAULT_CC +tcp_bind_flags(int sck, char* addr, char* port, int flags); + +/** + * + * @brief Binds the listening socket + * @param sck Listening socket + * @param addr Listening address + * @param port Listening port * @return 0 on success, -1 on error * */ diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/vnc/Makefile.am posixrdp/posixxrdp.orig/vnc/Makefile.am --- xrdp/xrdp-0.5.0~20100303cvs.orig/vnc/Makefile.am 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/vnc/Makefile.am 2010-11-08 09:56:45.000000000 +0100 @@ -1,9 +1,17 @@ AM_CFLAGS = \ + -pthread \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ -DXRDP_SBIN_PATH=\"${sbindir}\" \ -DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \ - -DXRDP_PID_PATH=\"${localstatedir}/run\" + -DXRDP_PID_PATH=\"${localstatedir}/run\" \ + -D_FILE_OFFSET_BITS=64 \ + -D_REENTRANT \ + -D_GNU_SOURCE \ + -D_XOPEN_SOURCE_EXTENDED + +AM_LDFLAGS = \ + -lpthread INCLUDES = \ -I$(top_srcdir)/common @@ -14,4 +22,4 @@ libvnc_la_SOURCES = vnc.c libvnc_la_LIBADD = \ - $(top_srcdir)/common/libcommon.la + $(top_builddir)/common/libcommon.la diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/vnc/vnc.c posixrdp/posixxrdp.orig/vnc/vnc.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/vnc/vnc.c 2010-11-02 11:51:10.000000000 +0100 +++ posixrdp/posixxrdp.orig/vnc/vnc.c 2010-11-08 09:56:45.000000000 +0100 @@ -21,6 +21,7 @@ */ #include "vnc.h" +#include "dbg.h" /******************************************************************************/ /* taken from vncauth.c */ @@ -29,6 +30,7 @@ { char key[12]; + VLOG("rfbEncryptBytes() called: bytes = %s; passwd = %s\0",bytes,passwd); /* key is simply password padded with nulls */ g_memset(key, 0, sizeof(key)); g_strncpy(key, passwd, 8); @@ -44,6 +46,8 @@ { int rcvd; + VLOG("lib_recv() called: data = %s; len = %d\0",data,len); + if (v->sck_closed) { return 1; @@ -87,6 +91,8 @@ { int sent; + VLOG("lib_send() called: data = %s; len = %d\0",data,len); + if (v->sck_closed) { return 1; @@ -135,6 +141,8 @@ int format; struct stream* out_s; + VLOG("lib_process_channel_data() called\0"); + if (chanid == v->clip_chanid) { in_uint16_le(s, type); @@ -226,7 +234,6 @@ int chanid; int flags; char* data; - char text[256]; error = 0; make_stream(s); @@ -255,29 +262,12 @@ key = param2; if (key > 0) { - if (key == 65027) /* altgr */ - { - if (v->shift_state) - { - /* fix for mstsc sending left control down with altgr */ - init_stream(s, 8192); - out_uint8(s, 4); - out_uint8(s, 0); /* down flag */ - out_uint8s(s, 2); - out_uint32_be(s, 65507); /* left control */ - lib_send(v, s->data, 8); - } - } init_stream(s, 8192); out_uint8(s, 4); out_uint8(s, msg == 15); /* down flag */ out_uint8s(s, 2); out_uint32_be(s, key); error = lib_send(v, s->data, 8); - if (key == 65507) /* left control */ - { - v->shift_state = msg == 15; - } } } else if (msg >= 100 && msg <= 110) /* mouse events */ @@ -327,8 +317,8 @@ int DEFAULT_CC get_pixel_safe(char* data, int x, int y, int width, int height, int bpp) { - int start; - int shift; + int start = 0; + int shift = 0; if (x < 0) { @@ -391,8 +381,8 @@ set_pixel_safe(char* data, int x, int y, int width, int height, int bpp, int pixel) { - int start; - int shift; + int start = 0; + int shift = 0; if (x < 0) { @@ -828,12 +818,11 @@ v->server_msg(v, "started connecting", 0); check_sec_result = 1; - /* only support 8 and 16 bpp connections from rdp client */ + /* only support 8, 16 or 24 bpp connections from rdp clients */ if ((v->server_bpp != 8) && (v->server_bpp != 15) && (v->server_bpp != 16) && (v->server_bpp != 24)) { - v->server_msg(v, "error - only supporting 8, 15, 16 and 24 bpp rdp \ -connections", 0); + v->server_msg(v, "error - only 8, 15, 16 and 24 bpp RDP connections are supported", 0); return 1; } if (g_strcmp(v->ip, "") == 0) @@ -1073,7 +1062,7 @@ { if (v->server_bpp != v->mod_bpp) { - v->server_msg(v, "error - server and client bpp don't match", 0); + v->server_msg(v, "error - server bpp and client bpp do not match", 0); error = 1; } } diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/xrdp/lang.c posixrdp/posixxrdp.orig/xrdp/lang.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/xrdp/lang.c 2010-11-02 11:51:10.000000000 +0100 +++ posixrdp/posixxrdp.orig/xrdp/lang.c 2010-11-08 09:56:44.000000000 +0100 @@ -234,13 +234,6 @@ g_file_close(fd); } } - else if (keylayout != 0x409) - { - g_free(filename); - g_writeln("keymap for 0x%4.4x was not found. Falling back to 0x0409 instead", - keylayout); - return get_keymaps(0x409, keymap); - } g_free(filename); return 0; } diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/xrdp/Makefile.am posixrdp/posixxrdp.orig/xrdp/Makefile.am --- xrdp/xrdp-0.5.0~20100303cvs.orig/xrdp/Makefile.am 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/xrdp/Makefile.am 2010-11-08 09:56:44.000000000 +0100 @@ -1,9 +1,17 @@ AM_CFLAGS = \ + -pthread \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ -DXRDP_SBIN_PATH=\"${sbindir}\" \ -DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \ - -DXRDP_PID_PATH=\"${localstatedir}/run\" + -DXRDP_PID_PATH=\"${localstatedir}/run\" \ + -D_FILE_OFFSET_BITS=64 \ + -D_REENTRANT \ + -D_GNU_SOURCE \ + -D_XOPEN_SOURCE_EXTENDED + +AM_LDFLAGS = \ + -lpthread INCLUDES = \ -I$(top_srcdir)/common \ @@ -28,8 +36,8 @@ xrdp_wm.c xrdp_LDADD = \ - $(top_srcdir)/common/libcommon.la \ - $(top_srcdir)/libxrdp/libxrdp.la + $(top_builddir)/common/libcommon.la \ + $(top_builddir)/libxrdp/libxrdp.la xrdpsysconfdir=$(sysconfdir)/xrdp diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/xrdp/xrdp_bitmap.c posixrdp/posixxrdp.orig/xrdp/xrdp_bitmap.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/xrdp/xrdp_bitmap.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/xrdp/xrdp_bitmap.c 2010-11-08 09:56:44.000000000 +0100 @@ -83,8 +83,8 @@ xrdp_bitmap_create(int width, int height, int bpp, int type, struct xrdp_wm* wm) { - struct xrdp_bitmap* self; - int Bpp; + struct xrdp_bitmap* self = (struct xrdp_bitmap *)NULL; + int Bpp = 0; self = (struct xrdp_bitmap*)g_malloc(sizeof(struct xrdp_bitmap), 1); self->type = type; @@ -124,7 +124,7 @@ int bpp, char* data, struct xrdp_wm* wm) { - struct xrdp_bitmap* self; + struct xrdp_bitmap* self = (struct xrdp_bitmap *)NULL; self = (struct xrdp_bitmap*)g_malloc(sizeof(struct xrdp_bitmap), 1); self->type = WND_TYPE_BITMAP; @@ -141,8 +141,8 @@ void APP_CC xrdp_bitmap_delete(struct xrdp_bitmap* self) { - int i; - struct xrdp_mod_data* mod_data; + int i = 0; + struct xrdp_mod_data* mod_data = (struct xrdp_mod_data *)NULL; if (self == 0) { @@ -227,8 +227,8 @@ struct xrdp_bitmap* APP_CC xrdp_bitmap_get_child_by_id(struct xrdp_bitmap* self, int id) { - int i; - struct xrdp_bitmap* b; + int i = 0; + struct xrdp_bitmap* b = (struct xrdp_bitmap *)NULL; for (i = 0; i < self->child_list->count; i++) { @@ -247,7 +247,7 @@ int APP_CC xrdp_bitmap_set_focus(struct xrdp_bitmap* self, int focused) { - struct xrdp_painter* painter; + struct xrdp_painter* painter = (struct xrdp_painter *)NULL; if (self == 0) { @@ -284,9 +284,9 @@ static int APP_CC xrdp_bitmap_get_index(struct xrdp_bitmap* self, int* palette, int color) { - int r; - int g; - int b; + int r = 0; + int g = 0; + int b = 0; r = (color & 0xff0000) >> 16; g = (color & 0x00ff00) >> 8; @@ -302,7 +302,7 @@ int APP_CC xrdp_bitmap_resize(struct xrdp_bitmap* self, int width, int height) { - int Bpp; + int Bpp = 0; if ((width == self->width) && (height == self->height)) { @@ -320,6 +320,7 @@ case 8: Bpp = 1; break; case 15: Bpp = 2; break; case 16: Bpp = 2; break; + /* case 24: Bpp = 3; break; */ } g_free(self->data); self->data = (char*)g_malloc(width * height * Bpp, 0); @@ -334,16 +335,20 @@ int APP_CC xrdp_bitmap_load(struct xrdp_bitmap* self, const char* filename, int* palette) { - int fd; - int i; - int j; - int k; - int color; - int size; + int fd = 0; + int i = 0; + int j = 0; + int k = 0; + int color = 0; + int size = 0; int palette1[256]; char type1[4]; struct xrdp_bmp_header header; - struct stream* s; + struct stream* s = (struct stream *)NULL; + + g_memset(palette1,0,sizeof(int) * 256); + g_memset(type1,0,sizeof(char) * 4); + g_memset(&header,0,sizeof(struct xrdp_bmp_header)); if (!g_file_exist(filename)) { @@ -351,7 +356,7 @@ filename); return 1; } - s = 0; + s = (struct stream *)NULL; fd = g_file_open(filename); if (fd != -1) { @@ -588,7 +593,7 @@ { return GETPIXEL16(self->data, x, y, self->width); } - else if (self->bpp == 24) + else if (self->bpp == 24 || self->bpp == 32) { return GETPIXEL32(self->data, x, y, self->width); } @@ -618,7 +623,7 @@ { SETPIXEL16(self->data, x, y, self->width, pixel); } - else if (self->bpp == 24) + else if (self->bpp == 24 || self->bpp == 32) { SETPIXEL32(self->data, x, y, self->width, pixel); } @@ -634,11 +639,11 @@ struct xrdp_bitmap* dest, int x, int y, int cx, int cy) { - int i; - int j; - int destx; - int desty; - int pixel; + int i = 0; + int j = 0; + int destx = 0; + int desty = 0; + int pixel = 0; if (self == 0) { @@ -670,7 +675,7 @@ { return 1; } - if (self->bpp == 24) + if (self->bpp == 24 || self->bpp == 32) { for (i = 0; i < cy; i++) { @@ -718,18 +723,18 @@ struct xrdp_bitmap* dest, int x, int y, int cx, int cy) { - int i; - int j; - int destx; - int desty; - int pixel; - int crc; - int incs; - int incd; - unsigned char* s8; - unsigned char* d8; - unsigned short* s16; - unsigned short* d16; + int i = 0; + int j = 0; + int destx = 0; + int desty = 0; + int pixel = 0; + int crc = 0; + int incs = 0; + int incd = 0; + unsigned char* s8 = (unsigned char *)NULL; + unsigned char* d8 = (unsigned char *)NULL; + unsigned short* s16 = (unsigned short *)NULL; + unsigned short* d16 = (unsigned short *)NULL; if (self == 0) { @@ -761,8 +766,9 @@ { return 1; } + crc = dest->crc; CRC_START(crc); - if (self->bpp == 24) + if (self->bpp == 24 || self->bpp == 32) { for (i = 0; i < cy; i++) { diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/xrdp/xrdp.c posixrdp/posixxrdp.orig/xrdp/xrdp.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/xrdp/xrdp.c 2010-11-02 11:51:10.000000000 +0100 +++ posixrdp/posixxrdp.orig/xrdp/xrdp.c 2010-11-08 09:56:44.000000000 +0100 @@ -32,8 +32,8 @@ static SERVICE_STATUS_HANDLE g_ssh = 0; static SERVICE_STATUS g_service_status; #endif -static long g_sync_mutex = 0; -static long g_sync1_mutex = 0; +static tc_p g_sync_mutex = 0; +static tc_p g_sync1_mutex = 0; static tbus g_term_event = 0; static tbus g_sync_event = 0; /* syncronize stuff */ @@ -533,10 +533,21 @@ } if (0 != pid) { - /* g_writeln("process %d started ok", pid); */ + g_writeln("process %d started ok", pid); /* exit, this is the main process */ g_exit(0); } + g_sleep(1000); + g_file_close(0); + g_file_close(1); + g_file_close(2); + g_file_open("/dev/null"); + g_file_open("/dev/null"); + g_file_open("/dev/null"); + /* end of daemonizing code */ + } + if (!no_daemon) + { /* write the pid to file */ pid = g_getpid(); fd = g_file_open(pid_file); /* xrdp.pid */ @@ -552,14 +563,6 @@ g_file_write(fd, text, g_strlen(text)); g_file_close(fd); } - g_sleep(1000); - g_file_close(0); - g_file_close(1); - g_file_close(2); - g_file_open("/dev/null"); - g_file_open("/dev/null"); - g_file_open("/dev/null"); - /* end of daemonizing code */ } #endif g_threadid = tc_get_threadid(); diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/xrdp/xrdp_cache.c posixrdp/posixxrdp.orig/xrdp/xrdp_cache.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/xrdp/xrdp_cache.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/xrdp/xrdp_cache.c 2010-11-08 09:56:44.000000000 +0100 @@ -128,21 +128,21 @@ int APP_CC xrdp_cache_add_bitmap(struct xrdp_cache* self, struct xrdp_bitmap* bitmap) { - int i; - int j; - int oldest; - int cache_id; - int cache_idx; - int bmp_size; - int e; - int Bpp; + int i = 0; + int j = 0; + int oldest = 0; + int cache_id = 0; + int cache_idx = 0; + int bmp_size = 0; + int e = 0; + int Bpp = 0; e = bitmap->width % 4; if (e != 0) { e = 4 - e; } - Bpp = (bitmap->bpp + 7) / 8; + Bpp = (bitmap->bpp == 32) ? 3 : (bitmap->bpp + 7) / 8; bmp_size = (bitmap->width + e) * bitmap->height * Bpp; self->bitmap_stamp++; /* look for match */ diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/xrdp/xrdp.ini posixrdp/posixxrdp.orig/xrdp/xrdp.ini --- xrdp/xrdp-0.5.0~20100303cvs.orig/xrdp/xrdp.ini 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/xrdp/xrdp.ini 2010-11-08 09:56:44.000000000 +0100 @@ -7,46 +7,16 @@ channel_code=1 [xrdp1] -name=sesman-Xvnc -lib=libvnc.so +name=sesman-X11rdp +lib=libxup.so username=ask password=ask -ip=127.0.0.1 +ip=::1 port=-1 [xrdp2] -name=console -lib=libvnc.so -ip=127.0.0.1 -port=5900 -username=na -password=ask - -[xrdp3] -name=vnc-any -lib=libvnc.so -ip=ask -port=ask5900 -username=na -password=ask - -[xrdp4] -name=sesman-any +name=sesman-Xvnc lib=libvnc.so -ip=ask -port=-1 -username=ask -password=ask - -[xrdp5] -name=rdp-any -lib=librdp.so -ip=ask -port=ask3389 - -[xrdp6] -name=sesman-X11rdp -lib=libxup.so username=ask password=ask ip=127.0.0.1 diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/xrdp/xrdp_listen.c posixrdp/posixxrdp.orig/xrdp/xrdp_listen.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/xrdp/xrdp_listen.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/xrdp/xrdp_listen.c 2010-11-08 09:56:44.000000000 +0100 @@ -20,11 +20,13 @@ */ +#include #include "xrdp.h" +#include "dbg.h" /* 'g_process' is protected by the semaphore 'g_process_sem'. One thread sets g_process and waits for the other to process it */ -static tbus g_process_sem = 0; +static tc_p g_process_sem = 0; static struct xrdp_process* g_process = 0; /*****************************************************************************/ @@ -166,6 +168,7 @@ int error; int robjs_count; int cont; + int flags = 0; char port[8]; tbus robjs[8]; tbus term_obj; @@ -178,7 +181,8 @@ xrdp_listen_get_port(port, sizeof(port)); self->sck = g_tcp_socket(); g_tcp_set_non_blocking(self->sck); - error = g_tcp_bind(self->sck, port); + flags = AI_ADDRCONFIG | AI_PASSIVE; + error = g_tcp_bind_flags(self->sck, port, flags); if (error != 0) { g_writeln("bind error in xrdp_listen_main_loop"); @@ -217,7 +221,7 @@ g_reset_wait_obj(sync_obj); g_loop(); } - if (g_is_wait_obj_set(sck_obj)) /* incomming connection */ + if (g_is_wait_obj_set(sck_obj)) /* incoming connection */ { error = g_tcp_accept(self->sck); if ((error == -1) && g_tcp_last_error_would_block(self->sck)) diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/xrdp/xrdp_mm.c posixrdp/posixxrdp.orig/xrdp/xrdp_mm.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/xrdp/xrdp_mm.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/xrdp/xrdp_mm.c 2010-11-08 09:56:44.000000000 +0100 @@ -21,6 +21,7 @@ */ #include "xrdp.h" +#include "dbg.h" /*****************************************************************************/ struct xrdp_mm* APP_CC @@ -28,6 +29,8 @@ { struct xrdp_mm* self; + //DBGLOG("xrdp","[xrdp_mm_create()]"); + self = (struct xrdp_mm*)g_malloc(sizeof(struct xrdp_mm), 1); self->wm = owner; self->login_names = list_create(); @@ -42,6 +45,8 @@ static long DEFAULT_CC xrdp_mm_sync_unload(long param1, long param2) { + //DBGLOG("xrdp","[xrdp_mm_sync_unload()]"); + return g_free_library(param1); } @@ -53,6 +58,8 @@ long rv; char* libname; + //DBGLOG("xrdp","[xrdp_mm_sync_load()]"); + libname = (char*)param1; rv = g_load_library(libname); return rv; @@ -62,6 +69,8 @@ static void APP_CC xrdp_mm_module_cleanup(struct xrdp_mm* self) { + //DBGLOG("xrdp","[xrdp_mm_module_cleanup()]"); + if (self->mod != 0) { if (self->mod_exit != 0) @@ -88,6 +97,8 @@ void APP_CC xrdp_mm_delete(struct xrdp_mm* self) { + //DBGLOG("xrdp","[xrdp_mm_delete()]"); + if (self == 0) { return; @@ -106,16 +117,16 @@ static int APP_CC xrdp_mm_send_login(struct xrdp_mm* self) { - struct stream* s; - int rv; - int index; - int count; - char* username; - char* password; - char* name; - char* value; + struct stream * s = (struct stream *)NULL; + int rv = 0; + int index = 0; + int count = 0; + char * username = (char *)NULL; + char * password = (char *)NULL; + char * name = (char *)NULL; + char * value = (char *)NULL; - xrdp_wm_log_msg(self->wm, "sending login info to sesman"); + xrdp_wm_log_msg(self->wm, "Sending login information to sesman"); username = 0; password = 0; self->code = 0; @@ -143,9 +154,10 @@ } if ((username == 0) || (password == 0)) { - xrdp_wm_log_msg(self->wm, "error finding username and password"); + xrdp_wm_log_msg(self->wm, "Error finding username and password"); return 1; } + s = trans_get_out_s(self->sesman_trans, 8192); s_push_layer(s, channel_hdr, 8); /* this code is either 0 for Xvnc or 10 for X11rdp */ @@ -154,15 +166,18 @@ out_uint16_be(s, index); out_uint8a(s, username, index); index = g_strlen(password); + out_uint16_be(s, index); out_uint8a(s, password, index); out_uint16_be(s, self->wm->screen->width); out_uint16_be(s, self->wm->screen->height); out_uint16_be(s, self->wm->screen->bpp); + /* send domain */ index = g_strlen(self->wm->client_info->domain); out_uint16_be(s, index); out_uint8a(s, self->wm->client_info->domain, index); + /* send program / shell */ index = g_strlen(self->wm->client_info->program); out_uint16_be(s, index); @@ -171,16 +186,19 @@ index = g_strlen(self->wm->client_info->directory); out_uint16_be(s, index); out_uint8a(s, self->wm->client_info->directory, index); + s_mark_end(s); s_pop_layer(s, channel_hdr); out_uint32_be(s, 0); /* version */ index = (int)(s->end - s->data); out_uint32_be(s, index); /* size */ + rv = trans_force_write(self->sesman_trans); - if (rv != 0) - { - xrdp_wm_log_msg(self->wm, "xrdp_mm_send_login: xrdp_mm_send failed"); + + if (rv != 0) { + xrdp_wm_log_msg(self->wm, "xrdp_mm_send_login: xrdp_mm_send_login failed"); } + return rv; } @@ -216,6 +234,7 @@ rv = 0; } } + return rv; } @@ -237,6 +256,7 @@ g_snprintf(text, 255, "no library name specified in xrdp.ini, please add " "lib=libxrdp-vnc.so or similar"); xrdp_wm_log_msg(self->wm, text); + return 1; } if (lib[0] == 0) @@ -244,6 +264,7 @@ g_snprintf(text, 255, "empty library name specified in xrdp.ini, please " "add lib=libxrdp-vnc.so or similar"); xrdp_wm_log_msg(self->wm, text); + return 1; } if (self->mod_handle == 0) @@ -280,7 +301,7 @@ self->mod = self->mod_init(); if (self->mod != 0) { - g_writeln("loaded modual '%s' ok, interface size %d, version %d", lib, + g_writeln("loaded module '%s' ok, interface size %d, version %d", lib, self->mod->size, self->mod->version); } } @@ -334,13 +355,14 @@ xrdp_mm_setup_mod2(struct xrdp_mm* self) { char text[256]; - char* name; - char* value; - int i; - int rv; - int key_flags; - int device_flags; + char* name = (char *)NULL; + char* value = (char *)NULL; + int i = 0; + int rv = 0; + int key_flags = 0; + int device_flags = 0; + g_memset(text,0,sizeof(char) * 256); rv = 1; text[0] = 0; if (!g_is_wait_obj_set(self->wm->pro_layer->self_term_event)) @@ -432,13 +454,15 @@ static int APP_CC xrdp_mm_trans_send_channel_setup(struct xrdp_mm* self, struct trans* trans) { - int index; - int chan_id; - int chan_flags; - int size; - struct stream* s; + int index = 0; + int chan_id = 0; + int chan_flags = 0; + int size = 0; + struct stream* s = (struct stream *)NULL; char chan_name[256]; + g_memset(chan_name,0,sizeof(char) * 256); + s = trans_get_out_s(trans, 8192); if (s == 0) { @@ -477,7 +501,7 @@ xrdp_mm_trans_send_channel_data_response(struct xrdp_mm* self, struct trans* trans) { - struct stream* s; + struct stream* s = (struct stream *)NULL; s = trans_get_out_s(trans, 8192); if (s == 0) @@ -507,12 +531,12 @@ static int APP_CC xrdp_mm_trans_process_channel_data(struct xrdp_mm* self, struct trans* trans) { - struct stream* s; - int size; - int total_size; - int chan_id; - int chan_flags; - int rv; + struct stream* s = (struct stream *)NULL; + int size = 0; + int total_size = 0; + int chan_id = 0; + int chan_flags = 0; + int rv = 0; s = trans_get_in_s(trans); if (s == 0) @@ -539,10 +563,10 @@ xrdp_mm_chan_process_msg(struct xrdp_mm* self, struct trans* trans, struct stream* s) { - int rv; - int id; - int size; - char* next_msg; + int rv = 0; + int id = 0; + int size = 0; + char* next_msg = (char *)NULL; rv = 0; while (s_check_rem(s, 8)) @@ -579,14 +603,14 @@ /*****************************************************************************/ /* this is callback from trans obj returns error */ -static int APP_CC +static size_t APP_CC xrdp_mm_chan_data_in(struct trans* trans) { - struct xrdp_mm* self; - struct stream* s; - int id; - int size; - int error; + struct xrdp_mm* self = (struct xrdp_mm *)NULL; + struct stream* s = (struct stream *)NULL; + int id = 0; + int size = 0; + int error = 0; if (trans == 0) { @@ -613,7 +637,7 @@ static int APP_CC xrdp_mm_chan_send_init(struct xrdp_mm* self) { - struct stream* s; + struct stream* s = (struct stream *)NULL; s = trans_get_out_s(self->chan_trans, 8192); if (s == 0) @@ -632,14 +656,17 @@ static int APP_CC xrdp_mm_process_login_response(struct xrdp_mm* self, struct stream* s) { - int ok; - int display; - int rv; - int index; + int ok = 0; + int display = 0; + int rv = 0; + int index = 0; char text[256]; char ip[256]; char port[256]; + g_memset(text,0,sizeof(char) * 256); + g_memset(ip,0,sizeof(char) * 256); + g_memset(port,0,sizeof(char) * 256); rv = 0; in_uint16_be(s, ok); in_uint16_be(s, display); @@ -657,7 +684,7 @@ xrdp_wm_set_login_mode(self->wm, 10); self->wm->dragging = 0; /* connect channel redir */ - if (strcmp(ip, "127.0.0.1") == 0) + if ((ip == NULL) || (g_strcasecmp(ip, "") == 0) || (g_strcasecmp(ip, "socket") == 0) || (g_strcasecmp(ip, "localhost") == 0) || (g_strchr(ip, '/') != NULL)) { /* unix socket */ self->chan_trans = trans_create(2, 8192, 8192); @@ -672,10 +699,10 @@ self->chan_trans->trans_data_in = xrdp_mm_chan_data_in; self->chan_trans->header_size = 8; self->chan_trans->callback_data = self; - /* try to connect up to 4 times */ - for (index = 0; index < 4; index++) + /* try to connect up to 2 times */ + for (index = 0; index < 2; index++) { - if (trans_connect(self->chan_trans, ip, port, 3000) == 0) + if (trans_connect(self->chan_trans, ip, port, 2000) == 0) { self->chan_trans_up = 1; break; @@ -711,6 +738,7 @@ xrdp_wm_set_login_mode(self->wm, 11); xrdp_mm_module_cleanup(self); } + return rv; } @@ -718,14 +746,15 @@ static int xrdp_mm_get_sesman_port(char* port, int port_bytes) { - int fd; - int error; - int index; - char* val; + int fd = -1; + int error = 0; + int index = 0; + char* val = 0; char cfg_file[256]; - struct list* names; - struct list* values; + struct list* names = (struct list *)NULL; + struct list* values = (struct list *)NULL; + g_memset(cfg_file,0,sizeof(char) * 256); /* default to port 3350 */ g_strncpy(port, "3350", port_bytes - 1); /* see if port is in xrdp.ini file */ @@ -761,6 +790,7 @@ list_delete(values); g_file_close(fd); } + return 0; } @@ -771,13 +801,13 @@ xrdp_mm_process_channel_data(struct xrdp_mm* self, tbus param1, tbus param2, tbus param3, tbus param4) { - struct stream* s; - int rv; - int length; - int total_length; - int flags; - int id; - char* data; + struct stream* s = (struct stream *)NULL; + int rv = 0; + int length = 0; + int total_length = 0; + int flags = 0; + int id = 0; + char * data = (char *)NULL; rv = 0; if ((self->chan_trans != 0) && self->chan_trans_up) @@ -792,7 +822,7 @@ total_length = param4; if (total_length < length) { - g_writeln("warning in xrdp_mm_process_channel_data total_len < length"); + g_writeln("WARNING in xrdp_mm_process_channel_data(): total_len < length"); total_length = length; } out_uint32_le(s, 0); /* version */ @@ -808,19 +838,20 @@ rv = trans_force_write(self->chan_trans); } } + return rv; } /*****************************************************************************/ -static int APP_CC +static size_t APP_CC xrdp_mm_sesman_data_in(struct trans* trans) { - struct xrdp_mm* self; - struct stream* s; - int version; - int size; - int error; - int code; + struct xrdp_mm* self = (struct xrdp_mm *)NULL; + struct stream* s = (struct stream *)NULL; + int version = 0; + int size = 0; + int error = 0; + int code = 0; if (trans == 0) { @@ -848,6 +879,7 @@ break; } } + return error; } @@ -855,21 +887,25 @@ int APP_CC xrdp_mm_connect(struct xrdp_mm* self) { - struct list* names; - struct list* values; - int index; - int count; - int use_sesman; - int error; - int ok; - int rv; - char* name; - char* value; + struct list* names = (struct list *)NULL; + struct list* values = (struct list *)NULL; + int index = 0; + int count = 0; + int use_sesman = 0; + int error = 0; + int ok = 0; + int rv = 0; + char* name = (char *)NULL; + char* value = (char *)NULL; char ip[256]; char errstr[256]; char text[256]; char port[8]; + g_memset(ip,0,sizeof(char) * 256); + g_memset(errstr,0,sizeof(char) * 256); + g_memset(text,0,sizeof(char) * 256); + g_memset(port,0,sizeof(char) * 8); rv = 0; use_sesman = 0; names = self->login_names; @@ -949,6 +985,7 @@ } } self->sesman_controlled = use_sesman; + return rv; } @@ -958,7 +995,7 @@ tbus* read_objs, int* rcount, tbus* write_objs, int* wcount, int* timeout) { - int rv; + int rv = 0; if (self == 0) { @@ -981,6 +1018,7 @@ write_objs, wcount, timeout); } } + return rv; } @@ -988,7 +1026,7 @@ int APP_CC xrdp_mm_check_wait_objs(struct xrdp_mm* self) { - int rv; + int rv = 0; if (self == 0) { @@ -1030,6 +1068,7 @@ self->chan_trans_up = 0; self->delete_chan_trans = 0; } + return rv; } @@ -1037,13 +1076,14 @@ int DEFAULT_CC server_begin_update(struct xrdp_mod* mod) { - struct xrdp_wm* wm; - struct xrdp_painter* p; + struct xrdp_wm* wm = (struct xrdp_wm *)NULL; + struct xrdp_painter* p = (struct xrdp_painter *)NULL; wm = (struct xrdp_wm*)(mod->wm); p = xrdp_painter_create(wm, wm->session); xrdp_painter_begin_update(p); mod->painter = (long)p; + return 0; } @@ -1051,12 +1091,13 @@ int DEFAULT_CC server_end_update(struct xrdp_mod* mod) { - struct xrdp_painter* p; + struct xrdp_painter* p = (struct xrdp_painter *)NULL; p = (struct xrdp_painter*)(mod->painter); xrdp_painter_end_update(p); xrdp_painter_delete(p); mod->painter = 0; + return 0; } @@ -1064,8 +1105,8 @@ int DEFAULT_CC server_fill_rect(struct xrdp_mod* mod, int x, int y, int cx, int cy) { - struct xrdp_wm* wm; - struct xrdp_painter* p; + struct xrdp_wm* wm = (struct xrdp_wm *)NULL; + struct xrdp_painter* p = (struct xrdp_painter *)NULL; wm = (struct xrdp_wm*)(mod->wm); p = (struct xrdp_painter*)(mod->painter); @@ -1302,7 +1343,7 @@ int DEFAULT_CC server_reset(struct xrdp_mod* mod, int width, int height, int bpp) { - struct xrdp_wm* wm; + struct xrdp_wm* wm = (struct xrdp_wm *)NULL; wm = (struct xrdp_wm*)(mod->wm); if (wm->client_info == 0) @@ -1342,7 +1383,7 @@ server_query_channel(struct xrdp_mod* mod, int index, char* channel_name, int* channel_flags) { - struct xrdp_wm* wm; + struct xrdp_wm* wm = (struct xrdp_wm *)NULL; wm = (struct xrdp_wm*)(mod->wm); if (wm->mm->sesman_controlled) @@ -1358,7 +1399,7 @@ int DEFAULT_CC server_get_channel_id(struct xrdp_mod* mod, char* name) { - struct xrdp_wm* wm; + struct xrdp_wm* wm = (struct xrdp_wm *)NULL; wm = (struct xrdp_wm*)(mod->wm); if (wm->mm->sesman_controlled) @@ -1374,7 +1415,7 @@ char* data, int data_len, int total_data_len, int flags) { - struct xrdp_wm* wm; + struct xrdp_wm* wm = (struct xrdp_wm *)NULL; wm = (struct xrdp_wm*)(mod->wm); if (wm->mm->sesman_controlled) diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/xrdp/xrdp_wm.c posixrdp/posixxrdp.orig/xrdp/xrdp_wm.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/xrdp/xrdp_wm.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/xrdp/xrdp_wm.c 2010-11-08 09:56:44.000000000 +0100 @@ -27,10 +27,15 @@ xrdp_wm_create(struct xrdp_process* owner, struct xrdp_client_info* client_info) { - struct xrdp_wm* self; + struct xrdp_wm* self = (struct xrdp_wm *)NULL; char event_name[256]; - int pid; + int pid = 0; + unsigned int bpp = 0; + /* initialize (zero out) local variables: */ + memset(event_name,0,sizeof(char) * 256); + + bpp = (client_info->bpp < 32) ? client_info->bpp : 24; self = (struct xrdp_wm*)g_malloc(sizeof(struct xrdp_wm), 1); self->client_info = client_info; self->screen = xrdp_bitmap_create(client_info->width, @@ -340,6 +345,17 @@ self->red = COLOR24BGR(0xff, 0x00, 0x00); self->green = COLOR24BGR(0x00, 0xff, 0x00); } + else if (self->screen->bpp == 32) + { + self->black = COLOR24BGR(0, 0, 0); + self->grey = COLOR24BGR(0xc0, 0xc0, 0xc0); + self->dark_grey = COLOR24BGR(0x80, 0x80, 0x80); + self->blue = COLOR24BGR(0x00, 0x00, 0xff); + self->dark_blue = COLOR24BGR(0x00, 0x00, 0x7f); + self->white = COLOR24BGR(0xff, 0xff, 0xff); + self->red = COLOR24BGR(0xff, 0x00, 0x00); + self->green = COLOR24BGR(0x00, 0xff, 0x00); + } return 0; } diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/xup/Makefile.am posixrdp/posixxrdp.orig/xup/Makefile.am --- xrdp/xrdp-0.5.0~20100303cvs.orig/xup/Makefile.am 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/xup/Makefile.am 2010-11-08 09:56:45.000000000 +0100 @@ -1,9 +1,17 @@ AM_CFLAGS = \ + -pthread \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ -DXRDP_SBIN_PATH=\"${sbindir}\" \ -DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \ - -DXRDP_PID_PATH=\"${localstatedir}/run\" + -DXRDP_PID_PATH=\"${localstatedir}/run\" \ + -D_FILE_OFFSET_BITS=64 \ + -D_REENTRANT \ + -D_GNU_SOURCE \ + -D_XOPEN_SOURCE_EXTENDED + +AM_LDFLAGS = \ + -lpthread INCLUDES = \ -I$(top_srcdir)/common @@ -14,4 +22,4 @@ libxup_la_SOURCES = xup.c libxup_la_LIBADD = \ - $(top_srcdir)/common/libcommon.la + $(top_builddir)/common/libcommon.la diff -Naru xrdp/xrdp-0.5.0~20100303cvs.orig/xup/xup.c posixrdp/posixxrdp.orig/xup/xup.c --- xrdp/xrdp-0.5.0~20100303cvs.orig/xup/xup.c 2010-03-04 08:16:34.000000000 +0100 +++ posixrdp/posixxrdp.orig/xup/xup.c 2010-11-08 09:56:45.000000000 +0100 @@ -140,11 +140,11 @@ mod->server_fill_rect(mod, 0, 0, mod->width, mod->height); mod->server_end_update(mod); mod->server_msg(mod, "started connecting", 0); - /* only support 8 and 16 bpp connections from rdp client */ - if (mod->bpp != 8 && mod->bpp != 16) + /* only support 8, 15, 16, 24 and 32 bpp connections from rdp clients */ + if (mod->bpp != 8 && mod->bpp != 15 && mod->bpp != 16 && mod->bpp != 24 && mod->bpp != 32) { mod->server_msg(mod, - "error - only supporting 8 and 16 bpp rdp connections", 0); + "ERROR: only 8-, 15-, 16-, 24-, or 32-bpp RDP connections are supported", 0); LIB_DEBUG(mod, "out lib_mod_connect error"); return 1; } @@ -194,9 +194,9 @@ g_tcp_close(mod->sck); mod->sck = 0; i++; - if (i >= 4) + if (i >= 2) { - mod->server_msg(mod, "connect problem, giving up", 0); + mod->server_msg(mod, "connection problem, giving up", 0); break; } g_sleep(250);