From: <ped...@us...> - 2007-06-24 22:26:08
|
Revision: 1001 http://svn.sourceforge.net/cegcc/?rev=1001&view=rev Author: pedroalves Date: 2007-06-24 15:26:06 -0700 (Sun, 24 Jun 2007) Log Message: ----------- * LICENSE, README, TODO: New files. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog Added Paths: ----------- trunk/cegcc/tools/PipeLib/LICENSE trunk/cegcc/tools/PipeLib/README trunk/cegcc/tools/PipeLib/TODO Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-24 22:25:10 UTC (rev 1000) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-24 22:26:06 UTC (rev 1001) @@ -1,3 +1,7 @@ +2007-06-24 Pedro Alves <ped...@po...> + + * LICENSE, README, TODO: New files. + 2007-06-09 Pedro Alves <ped...@po...> Initial import. Added: trunk/cegcc/tools/PipeLib/LICENSE =================================================================== --- trunk/cegcc/tools/PipeLib/LICENSE (rev 0) +++ trunk/cegcc/tools/PipeLib/LICENSE 2007-06-24 22:26:06 UTC (rev 1001) @@ -0,0 +1,25 @@ +/* Copyright (c) 2007, Pedro Alves + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ Added: trunk/cegcc/tools/PipeLib/README =================================================================== --- trunk/cegcc/tools/PipeLib/README (rev 0) +++ trunk/cegcc/tools/PipeLib/README 2007-06-24 22:26:06 UTC (rev 1001) @@ -0,0 +1,45 @@ + README for PipeLib + +This directory contains the PipeLib enhancer for Windows CE. + +PipeLib implements a stream driver that is exposed in an interface +similar to unnamed pipes on desktop Windows. Namelly, pipes are +created with CreatePipe and the pipe ends are manipulated with the normal +ReadFileW/WriteFileW/CloseHandle coredll.dll functions. + +To build the lib and the driver you will need the arm-wince-mingw32ce +toolchain. An early version of PipeLib was also tested with MSVC2005, +but project files aren't presently included. + +To build, ensure you have arm-wince-mingw32ce-gcc in your $PATH, and +type: + +make + +If you have synce-tools installed, type: + +make download + +The previous command will copy the driver (PipeDev.dll) to \Windows on +the device. + +If you don't have synce-tools installed, then copy the newly built +PipeDev.dll file into the \Windows on the device. + +PipeLib comes with a sample tester, but the main testbed client is +currently the rshd server for Windows CE found at +http://cegcc.sourceforge.net. Both PipeLib and rshd share the same +repository, so be sure you have a checkout from the same date before +reporting bugs. + +Have fun! + +Pedro Alves + +-- + +See the file LICENSE in the various directories, for a description of +the license the software is license in. + +REPORTING BUGS: ceg...@so... +pe...@po... Property changes on: trunk/cegcc/tools/PipeLib/README ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/cegcc/tools/PipeLib/TODO =================================================================== --- trunk/cegcc/tools/PipeLib/TODO (rev 0) +++ trunk/cegcc/tools/PipeLib/TODO 2007-06-24 22:26:06 UTC (rev 1001) @@ -0,0 +1,4 @@ +- Add SetLastError in all the error code paths. + +- Add to libPipeLib.a some more pipe related calls, following the + interface exposed on desktop Windows. To be added on a need basis. Property changes on: trunk/cegcc/tools/PipeLib/TODO ___________________________________________________________________ Name: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-24 22:53:27
|
Revision: 1002 http://svn.sourceforge.net/cegcc/?rev=1002&view=rev Author: pedroalves Date: 2007-06-24 15:53:21 -0700 (Sun, 24 Jun 2007) Log Message: ----------- Make PipeLib closer to desktop Windows Pipes. * PipeDev/Makefile (STRIP): New. (PipeDev.dll): Rename to ... (PipeDev_unstripped.dll): ... this. Add Makefile to dependencies. (PipeDev.dll): New rule for stripped version of PipeDev_unstripped.dll. (download): New rule. (.PHONY): Fix typo. Add download. * PipeDev/PipeDevice.cpp (LogMessage2): New. (LogMessage): Provide more info. Call LogMessage2. (LogScope::LogScope): Add MSG parameter. Change output to ">". (LogScope::~LogScope): Change output to "<". (LogScope::msg_): New field. (LOG): New macro. (LOGSCOPE): Pass __FUNCTION__ and __LINE__. Expect a char* as parameter. (GetDeviceHandle): Use new LOGSCOPE interface. (Init): Use new LOGSCOPE interface. Use LOG. (Deinit): Likewise. (Open): Likewise. (DeactivatorData): Delete. (Deactivator): Change void* parameter to HANDLE. Use new LOGSCOPE interface. Use LOG. Adapt to get the device HANDLE directly from the parameter. (DeactivatePipeDevice): Use new LOGSCOPE interface. Pass device->dev directly to CreateThread as start routine data. (Close): Use LOG. Add a comment explaining why we deactivate the device in a separate thread. (Read): Use new LOGSCOPE interface. Use LOG. Return success if the pipe is broken but the buffer still has data. Return success and don't block waiting for a Write if the read didn't fill the in buffer, but did get more than 0 bytes. Add a few comments explaing the code. (Write): Use new LOGSCOPE interface. Use LOG. Use IsBadWritePtr instead of IsBadReadPtr. Set ERROR_NO_DATA in case the pipe was broken. (Seek): Use new LOGSCOPE interface. (IOControl): Use new LOGSCOPE interface. Use LOG. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog trunk/cegcc/tools/PipeLib/PipeDev/Makefile trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-24 22:26:06 UTC (rev 1001) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-24 22:53:21 UTC (rev 1002) @@ -1,11 +1,50 @@ 2007-06-24 Pedro Alves <ped...@po...> + Make PipeLib closer to desktop Windows Pipes. + * PipeDev/Makefile (STRIP): New. + (PipeDev.dll): Rename to ... + (PipeDev_unstripped.dll): ... this. Add Makefile to dependencies. + (PipeDev.dll): New rule for stripped version of PipeDev_unstripped.dll. + (download): New rule. + (.PHONY): Fix typo. Add download. + * PipeDev/PipeDevice.cpp (LogMessage2): New. + (LogMessage): Provide more info. Call LogMessage2. + (LogScope::LogScope): Add MSG parameter. Change output to ">". + (LogScope::~LogScope): Change output to "<". + (LogScope::msg_): New field. + (LOG): New macro. + (LOGSCOPE): Pass __FUNCTION__ and __LINE__. Expect a char* as + parameter. + (GetDeviceHandle): Use new LOGSCOPE interface. + (Init): Use new LOGSCOPE interface. Use LOG. + (Deinit): Likewise. + (Open): Likewise. + (DeactivatorData): Delete. + (Deactivator): Change void* parameter to HANDLE. Use new LOGSCOPE + interface. Use LOG. Adapt to get the device HANDLE directly from the + parameter. + (DeactivatePipeDevice): Use new LOGSCOPE interface. Pass + device->dev directly to CreateThread as start routine data. + (Close): Use LOG. Add a comment explaining why we deactivate the + device in a separate thread. + (Read): Use new LOGSCOPE interface. Use LOG. Return success if the + pipe is broken but the buffer still has data. Return success and + don't block waiting for a Write if the read didn't fill the in buffer, + but did get more than 0 bytes. Add a few comments explaing the code. + (Write): Use new LOGSCOPE interface. Use LOG. Use IsBadWritePtr + instead of IsBadReadPtr. Set ERROR_NO_DATA in case the pipe was + broken. + (Seek): Use new LOGSCOPE interface. + (IOControl): Use new LOGSCOPE interface. Use LOG. + +2007-06-24 Pedro Alves <ped...@po...> + * LICENSE, README, TODO: New files. 2007-06-09 Pedro Alves <ped...@po...> Initial import. - + * ChangeLog, PipeLib/Makefile, PipeLib/PipeLib.cpp, PipeLib/PipeLib.h, PipeDev/Makefile, PipeDev/PipeDevice.cpp, PipeDev/PipeDevice.h, PipeTest/Makefile, PipeTest/PipeTest.cpp, Modified: trunk/cegcc/tools/PipeLib/PipeDev/Makefile =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev/Makefile 2007-06-24 22:26:06 UTC (rev 1001) +++ trunk/cegcc/tools/PipeLib/PipeDev/Makefile 2007-06-24 22:53:21 UTC (rev 1002) @@ -2,6 +2,7 @@ CXX=$(TARGET)-g++ AR=$(TARGET)-ar +STRIP=$(TARGET)-strip WARNFLAGS=-Wall -Wextra @@ -11,10 +12,16 @@ all: PipeDev.dll -PipeDev.dll: PipeDevice.cpp +PipeDev_unstripped.dll: PipeDevice.cpp Makefile $(CXX) $< -shared -o $@ $(ALLFLAGS) +PipeDev.dll: PipeDev_unstripped.dll + $(STRIP) $< -o $@ + +download: PipeDev.dll + pcp PipeDev.dll ":/Windows/PipeDev.dll" + clean: rm -f PipeDev.dll -.PHONE: all clean +.PHONY: all clean download Modified: trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp 2007-06-24 22:26:06 UTC (rev 1001) +++ trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp 2007-06-24 22:53:21 UTC (rev 1002) @@ -219,18 +219,12 @@ #ifdef DEBUG_LOCKS LockGuard (int line, T &cs) : cs_(cs), lineno(line) { - WCHAR buf[100]; - wsprintf (buf, L"line : %d", line); - MessageBoxW(0, buf, L"lock", 0); - + LOG ("LockGuard: line : %d\n", line); cs_.Lock (); } ~LockGuard () { - WCHAR buf[100]; - wsprintf (buf, L"line : %d", lineno); - MessageBoxW(0, buf, L"unlock", 0); - + LOG ("~LockGuard: line : %d\n", lineno); cs_.Unlock (); } #else @@ -383,39 +377,59 @@ return TRUE; } +#ifdef DEBUG_MODE static void -LogMessage (const char* msg, ...) +LogMessage2 (const char* msg) { -#if 0 + FILE* log = fopen ("pipelog.txt", "a+"); + fprintf (log, "%s", msg); + fclose (log); +} + +static void +LogMessage (const char *file, int line, const char* msg, ...) +{ va_list ap; + char buf[1024]; + char *b = buf; va_start (ap, msg); - FILE* log = fopen ("log.txt", "a+"); - vfprintf (log, msg, ap); - fclose (log); + sprintf (b, "%08x: %s (%d): ", (unsigned) GetCurrentThreadId (), file, line); + b += strlen (b); + vsprintf (b, msg, ap); va_end (ap); -#else - (void)msg; -#endif + + LogMessage2 (buf); } struct LogScope { - explicit LogScope (const char* func) + explicit LogScope (const char *func, const char* msg) : func_(func) + , msg_(msg) { - LogMessage ("entering %s\n", func_); + char buf[512]; + sprintf (buf, "> %s", msg_); + LogMessage (func_, -1, buf); } ~LogScope () { - LogMessage ("leaving %s\n", func_); + char buf[512]; + sprintf (buf, "< %s", msg_); + LogMessage (func_, -1, buf); } const char* func_; + const char* msg_; }; -#define LOGSCOPE(MSG) LogScope scope ## __LINE__(#MSG) +# define LOG(MSG, ...) LogMessage (__FUNCTION__, __LINE__, MSG, ## __VA_ARGS__) +# define LOGSCOPE(MSG) LogScope scope ## __LINE__(__FUNCTION__, MSG) +#else +# define LOG(MSG, ...) do; while (0) +# define LOGSCOPE(MSG) do; while (0) +#endif -/* This is needed for MSVC. */ +/* This is needed for MSVC, but it makes no harm in gcc. */ struct ltwstr { bool operator () (const std::wstring& s1, const std::wstring& s2) const @@ -432,7 +446,7 @@ static HANDLE GetDeviceHandle (PipeDeviceContext* pDeviceContext) { - LOGSCOPE (GetDeviceHandle); + LOGSCOPE ("\n"); HKEY hActive; DWORD Type; HANDLE hDev = INVALID_HANDLE_VALUE; @@ -458,13 +472,11 @@ PIPEDEV_API DWORD Init (LPCTSTR pContext) { - LOGSCOPE ("Init"); + LOGSCOPE ("\n"); CSWrapper cs (&open_pipes_cs); LockGuard<CSWrapper> guard G(cs); -#ifdef DEBUG_MODE - MessageBoxW (0, pContext, L"Init", 0); -#endif + LOG ("%ls\n", pContext); /* TODO: The key here isn't exactly the best. Maybe we should use the device name instead, and get that from the registry - that would @@ -489,15 +501,14 @@ PIPEDEV_API BOOL Deinit (PipeDeviceContext* pDeviceContext) { - LOGSCOPE ("Deinit"); + LOGSCOPE ("\n"); /* All file handles must to be closed before deinitialising the driver. */ #ifdef DEBUG_MODE - WCHAR buf[100]; - wsprintf (buf, L"opencount %d : calls %d", pDeviceContext->OpenCount, - close_calls); - MessageBoxW (0, buf, L"Deinit", 0); + LOG ("oc %lu, wc: %lu, close_calls: %d\n", + dev->OpenCount, + dev->WROpenCount, close_calls); #endif if (pDeviceContext == NULL) @@ -510,9 +521,7 @@ return FALSE; } -#ifdef DEBUG_MODE - MessageBoxW (0, L"deactivate success", L"Deinit", 0); -#endif + LOG ("deactivate success\n"); /* Allow reuse. */ open_pipes.erase (pDeviceContext->ActivePath); @@ -527,105 +536,69 @@ PIPEDEV_API DWORD Open (PipeDeviceContext* pDeviceContext, DWORD AccessCode, DWORD ShareMode) { - LOGSCOPE ("Open"); + LOGSCOPE ("\n"); -#ifdef DEBUG_MODE - wchar_t buf[100]; - wsprintf (buf, L"opencount %d", pDeviceContext->OpenCount); - MessageBoxW (0, buf, L"open 1", 0); -#endif + LOG ("oc %lu, wc: %lu, AccessCode %x, ShareMode %x\n", + pDeviceContext->OpenCount, pDeviceContext->WROpenCount, + AccessCode, ShareMode); PipeOpenContext* pOpenContext = new PipeOpenContext (pDeviceContext, AccessCode, ShareMode); -#ifdef DEBUG_MODE - MessageBoxW (0, L"going to lock", L"open 2", 0); -#endif + LOG ("going to lock\n"); PipeDeviceContext::LockGuard guard G(*pOpenContext->DeviceContext); -#ifdef DEBUG_MODE - MessageBoxW (0, L"locked", L"open 3", 0); -#endif + LOG ("locked\n"); pDeviceContext->OpenCount++; if (AccessCode & GENERIC_WRITE) pDeviceContext->WROpenCount++; -#ifdef DEBUG_MODE - wsprintf (buf, L"opencount %d", pDeviceContext->OpenCount); - MessageBoxW (0, buf, L"open", 0); -#endif + LOG ("OpenCount: %lu, WROpenCount: %lu\n", + pDeviceContext->OpenCount, + pDeviceContext->WROpenCount); return (DWORD)pOpenContext; } -struct DeactivatorData -{ - HANDLE th; - HANDLE dev; -}; - static DWORD WINAPI -Deactivator (void* arg) +Deactivator (HANDLE dev) { - LOGSCOPE ("Deactivator"); + LOGSCOPE ("\n"); - DeactivatorData* data = (DeactivatorData*)arg; - -#ifdef DEBUG_MODE - wchar_t buf[100]; - wsprintf (buf, L"%x", data->dev); - MessageBoxW(0, buf, L"close: dev handle", 0); - if (!DeactivateDevice (data->dev)) - MessageBoxW(0, buf, L"deactivate failed", 0); + if (!DeactivateDevice (dev)) + LOG("deactivate failed\n"); else - MessageBoxW(0, buf, L"after deactivate", 0); -#else - DeactivateDevice (data->dev); -#endif + LOG("deactivate success\n"); - CloseHandle (data->th); - delete data; - return 0; } static void DeactivatePipeDevice (PipeDeviceContext* dev) { - LOGSCOPE ("DeactivatePipeDevice"); - + LOGSCOPE ("\n"); HANDLE hdev = GetDeviceHandle (dev); - DeactivatorData* data = new DeactivatorData (); - data->dev = hdev; - data->th = CreateThread (NULL, 0, Deactivator, data, - CREATE_SUSPENDED, NULL); - ResumeThread (data->th); + HANDLE h = CreateThread (NULL, 0, Deactivator, hdev, 0, NULL); + CloseHandle (h); } PIPEDEV_API BOOL Close (PipeOpenContext* pOpenContext) { - LOGSCOPE ("Close"); + LOGSCOPE ("\n"); #ifdef DEBUG_MODE close_calls++; +#endif - wchar_t buf[100]; if (pOpenContext) - { - wsprintf (buf, L"opencount %d : %p", - pOpenContext->DeviceContext->OpenCount, - pOpenContext); - MessageBoxW (0, buf, L"close", 0); - } + LOG ("oc %lu, wc: %lu\n", + pOpenContext->DeviceContext->OpenCount, + pOpenContext->DeviceContext->WROpenCount); else - { - wsprintf (buf, L"openctx %p", pOpenContext); - MessageBoxW (0, buf, L"close", 0); - } -#endif + LOG ("openctx %p\n", pOpenContext); if (pOpenContext == NULL) return FALSE; @@ -650,19 +623,15 @@ delete pOpenContext; -#ifdef DEBUG_MODE - wsprintf (buf, L"opencount %d", dev->OpenCount); - MessageBoxW (0, buf, L"close 2", 0); -#endif + LOG ("oc %lu, wc: %lu\n", + dev->OpenCount, dev->WROpenCount); if (dev->OpenCount == 0) { -#if 0 - HANDLE hdev = GetDeviceHandle (dev); - DeactivateDevice (hdev); -#else + /* Deactivating the device here seems to + corrupt the Device.exe, and sometimes hangs + the device. Do it in an auxilary thread. */ DeactivatePipeDevice (dev); -#endif } return TRUE; @@ -671,11 +640,12 @@ PIPEDEV_API DWORD Read (PipeOpenContext* pOpenContext, LPVOID pBuffer_, DWORD dwCount) { - LOGSCOPE ("Read"); + LOGSCOPE ("\n"); if (IsBadReadPtr (pBuffer_, dwCount)) { SetLastError (ERROR_INVALID_PARAMETER); + LOG ("\n"); return -1; } @@ -684,7 +654,10 @@ if (pOpenContext == NULL || (pOpenContext->dwAccessCode & GENERIC_READ) == 0) - return (DWORD)-1; + { + LOG ("Invalid access or no context\n"); + return (DWORD)-1; + } PipeDeviceContext* dev = pOpenContext->DeviceContext; @@ -699,18 +672,9 @@ Events[0] = dev->WriteEvent; Events[1] = dev->AbortEvent; - if (dev->Aborting) - /* this device is long gone */ - return (DWORD)-1; - - if (dev->WROpenCount == 0) - /* broken pipe */ - return (DWORD)-1; - - if (dev->OpenCount == 0) - /* weird */ - return (DWORD)-1; - + /* Read before checking for broken pipe, so + we get a chance to return valid data when that + happens. */ DWORD read = dev->readBytes (pBuffer, dwCount); pBuffer += read; dwCount -= read; @@ -718,53 +682,81 @@ if (read) SetEvent (dev->ReadEvent); - if (dwCount == 0) - break; + if (dev->Aborting /* this device is long gone, */ + || dev->WROpenCount == 0 /* or broken pipe */ + || dev->OpenCount == 0 /* or, ... weird */ + ) + { + SetLastError (ERROR_BROKEN_PIPE); + if (needed - dwCount) + { + /* I don't know a way to report error and 'valid + data' at the same time. Is there a way? Instead + we report 'valid' and the next Read call will error. */ + LOG ("Pipe broken, but with data\n"); + break; + } + LOG ("Pipe broken\n"); + return (DWORD) -1; + } + if (read || dwCount == 0) + { + /* We've either read something or pBuffer_ is full. */ + LOG ("read || dwCount == 0\n"); + break; + } + if (breaknext) break; } + /* The buffer was empty, wait for data. */ switch (WaitForMultipleObjects (2, Events, FALSE, INFINITE)) { case WAIT_OBJECT_0: + /* Data was written to the pipe. Do one more iteration + to fetch what we can and bail out. */ breaknext = TRUE; break; default: - // MessageBoxW (0, L"pipe aborted", L"Read", 0); /* With either wait error or AbortEvent signaled, return with error. */ - return (DWORD)-1; + LOG ("WaitForMultipleObjects default case\n"); + return (DWORD) -1; } } while (dwCount); + LOG ("Read: %u\n", needed - dwCount); return needed - dwCount; } PIPEDEV_API DWORD Write (PipeOpenContext* pOpenContext, LPCVOID pBuffer_, DWORD dwCount) { - LOGSCOPE ("Write"); + LOGSCOPE ("\n"); - if (IsBadReadPtr (pBuffer_, dwCount)) + if (IsBadWritePtr ((void*) pBuffer_, dwCount)) { SetLastError (ERROR_INVALID_PARAMETER); + LOG ("\n"); return -1; } const BYTE* pBuffer = (const BYTE*)pBuffer_; DWORD needed = dwCount; -#ifdef DEBUG_MODE - wchar_t buf[100]; - wsprintf (buf, L"opencount %d", pOpenContext->DeviceContext->OpenCount); - MessageBoxW (0, buf, L"write", 0); -#endif + LOG ("oc %lu, wc: %lu\n", + pOpenContext->DeviceContext->OpenCount, + pOpenContext->DeviceContext->WROpenCount); if (pOpenContext == NULL || (pOpenContext->dwAccessCode & GENERIC_WRITE) == 0) - return (DWORD)-1; + { + LOG ("Invalid access or no context\n"); + return (DWORD)-1; + } PipeDeviceContext* dev = pOpenContext->DeviceContext; @@ -776,24 +768,36 @@ { PipeDeviceContext::LockGuard guard G(*dev); -#ifdef DEBUG_MODE - MessageBoxW (0, L"lock acquired", L"write", 0); -#endif + LOG ("lock acquired\n"); Events[0] = dev->ReadEvent; Events[1] = dev->AbortEvent; if (dev->Aborting) - /* this device is long gone */ - return (DWORD)-1; + { + /* this device is long gone */ + SetLastError (ERROR_NO_DATA); + LOG ("Device is gone\n"); + return (DWORD)-1; + } if (dev->OpenCount == 0) - /* weird */ - return (DWORD)-1; + { + /* weird */ + SetLastError (ERROR_NO_DATA); + LOG ("Device is not open\n"); + return (DWORD)-1; + } - /* According to MSDN, attempting to read from a pipe without writers, - generates a broken pipe error, but the opposite isn't forbidden, so we - allow writing to a pipe without a reader. */ + if (dev->OpenCount == dev->WROpenCount) + { + /* no readers */ + SetLastError (ERROR_NO_DATA); + LOG ("No readers left: oc %lu, wc: %lu\n", + dev->OpenCount, + dev->WROpenCount); + return (DWORD)-1; + } DWORD wrote = dev->writeBytes (pBuffer, dwCount); pBuffer += wrote; @@ -816,21 +820,22 @@ breaknext = TRUE; break; default: - // MessageBoxW (0, L"pipe aborted", L"Write", 0); /* With either wait error or AbortEvent signaled, return with error. */ + LOG ("WaitForMultipleObjects default case\n"); return (DWORD) -1; } } while (dwCount); + LOG ("%u\n", needed - dwCount); return needed - dwCount; } PIPEDEV_API DWORD Seek (PipeOpenContext* /*pOpenContext*/, long /*Amount*/, WORD /*wType*/) { - LOGSCOPE ("Seek"); + LOGSCOPE ("\n"); /* Pipes don't support seeking. */ return (DWORD)-1; } @@ -840,7 +845,7 @@ PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut) { - LOGSCOPE ("IOControl"); + LOGSCOPE ("\n"); /* Kill unused warnings. */ (void)pBufIn; @@ -858,9 +863,7 @@ PipeDeviceContext::LockGuard guard G(*dev); #ifdef DEBUG_MODE - wchar_t buf[100]; - wsprintf (buf, L"%x : %d", dwCode, dev->OpenCount); - MessageBoxW (0, buf, L"IOControl", 0); + LOG ("%x : %d\n", dwCode, dev->OpenCount); #endif if (dwCode == IOCTL_PSL_NOTIFY) @@ -870,11 +873,7 @@ if (pPslPacket->dwSize == sizeof (DEVICE_PSL_NOTIFY) && pPslPacket->dwFlags == DLL_PROCESS_EXITING) { -#ifdef DEBUG_MODE - WCHAR buf[100]; - wsprintf (buf, L"%p : %p", pPslPacket->hProc, pPslPacket->hThread); - MessageBoxW(0, buf, L"process dying", 0); -#endif + LOG ("Process dying: %p : %p\n", pPslPacket->hProc, pPslPacket->hThread); dev->Aborting = TRUE; /* Unlock all blocked threads. */ SetEvent (dev->AbortEvent); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-24 22:58:15
|
Revision: 1003 http://svn.sourceforge.net/cegcc/?rev=1003&view=rev Author: pedroalves Date: 2007-06-24 15:58:14 -0700 (Sun, 24 Jun 2007) Log Message: ----------- * conformtest.c: New file. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog Added Paths: ----------- trunk/cegcc/tools/PipeLib/conformtest.c Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-24 22:53:21 UTC (rev 1002) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-24 22:58:14 UTC (rev 1003) @@ -1,4 +1,8 @@ 2007-06-24 Pedro Alves <ped...@po...> + + * conformtest.c: New file. + +2007-06-24 Pedro Alves <ped...@po...> Make PipeLib closer to desktop Windows Pipes. * PipeDev/Makefile (STRIP): New. Added: trunk/cegcc/tools/PipeLib/conformtest.c =================================================================== --- trunk/cegcc/tools/PipeLib/conformtest.c (rev 0) +++ trunk/cegcc/tools/PipeLib/conformtest.c 2007-06-24 22:58:14 UTC (rev 1003) @@ -0,0 +1,171 @@ +/* The plan is to evolve this file into some sort of conformance test. + The test should be performed on 9X/NT, and the results matched to + PipeLib. Currently the #if 0 parts were tested manually. They should + be moved into threads and WaitForSingleObject calls with timeouts, or + something. */ + +#include <windows.h> +#include <stdio.h> + +#ifndef COUNTOF +#define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0])) +#endif + +/* Map the Windows error number in ERROR to a locale-dependent error + message string and return a pointer to it. Typically, the values + for ERROR come from GetLastError. + + The string pointed to shall not be modified by the application, + but may be overwritten by a subsequent call to strwinerror + + The strwinerror function does not change the current setting + of GetLastError. */ + +static char * +strwinerror (DWORD error) +{ + static char buf[1024]; + wchar_t *msgbuf; + DWORD lasterr = GetLastError (); + DWORD chars = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) + { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' + && msgbuf[chars - 1] == '\n') + { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > ((COUNTOF (buf)) - 1)) + { + chars = COUNTOF (buf) - 1; + msgbuf [chars] = 0; + } + + sprintf (buf, "(%ld) %ls", error, msgbuf); + LocalFree (msgbuf); + } + else + sprintf (buf, "unknown win32 error (%ld)", error); + + SetLastError (lasterr); + return buf; +} + +static DWORD WINAPI +close_handle (HANDLE arg) +{ + + Sleep (3000); + printf ("closing handle\n"); + CloseHandle (arg); + + return 0; +} + +int main () +{ + DWORD written; + DWORD read; + const char str[] = "hello1\n"; + char buf[512]; + + HANDLE readh, writeh; + if (!CreatePipe (&readh, &writeh, NULL, 0)) + { + printf ("CreatePipe failed : %s\n", strwinerror (GetLastError ())); + return 1; + } + +#if 0 + CloseHandle (writeh); + + if (!ReadFile (readh, buf, 1, &read, FALSE)) + { + /* ERROR_BROKEN_PIPE */ + printf ("ReadFile: broken pipe? : %s\n", strwinerror (GetLastError ())); + return 3; + } +#endif + +#if 0 + CloseHandle (readh); + + if (!WriteFile (writeh, str, sizeof (str) - 1, &written, NULL)) + { + /* ERROR_NO_DATA */ + printf ("broken pipe? %s\n", strwinerror (GetLastError ())); + return 2; + } +#endif + +#if 0 + HANDLE thread = CreateThread (NULL, 0, close_handle, writeh, 0, NULL); + CloseHandle (thread); + + if (!ReadFile (readh, buf, 1, &read, FALSE)) + { + /* ERROR_BROKEN_PIPE */ + printf ("broken pipe : %s\n", strwinerror (GetLastError ())); + return 3; + } +#endif + +#if 1 + HANDLE thread = CreateThread (NULL, 0, close_handle, readh, 0, NULL); + CloseHandle (thread); + + DWORD count = 0; + while (1) + { + if (!WriteFile (writeh, str, sizeof (str) - 1, &written, NULL)) + { + /* ERROR_NO_DATA */ + printf ("broken pipe? %s\n", strwinerror (GetLastError ())); + return 2; + } + count += written; + /* Checking if WriteFile returns if *something* was written, or + if it always wait for flushing the buffer. */ + + /* I see that Windows return ERROR_NO_DATA, and reports that + sizeof (str) - 1 was written. I don't think we can do + that with WinCE. */ + if (1 || count % 100 == 0) + { + printf ("count = %d\n", count); + fflush (stdout); + } + } +#endif + + if (!ReadFile (readh, buf, sizeof (buf), &read, FALSE)) + { + printf ("broken pipe? : %s\n", strwinerror (GetLastError ())); + return 4; + } + + fwrite (buf, 1, read, stdout); + fflush (stdout); + + if (!ReadFile (readh, buf, sizeof (buf), &read, FALSE)) + { + printf ("broken pipe? : %s\n", strwinerror (GetLastError ())); + return 4; + } + + fwrite (buf, 1, read, stdout); + fflush (stdout); + + return 0; +} Property changes on: trunk/cegcc/tools/PipeLib/conformtest.c ___________________________________________________________________ Name: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-27 23:52:53
|
Revision: 1011 http://svn.sourceforge.net/cegcc/?rev=1011&view=rev Author: pedroalves Date: 2007-06-27 16:52:52 -0700 (Wed, 27 Jun 2007) Log Message: ----------- * PipeLib/PipeLib.h (SetPipeTag): Declare. * PipeLib/PipeLib.cpp (SetPipeTag): Define. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-26 00:32:57 UTC (rev 1010) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-27 23:52:52 UTC (rev 1011) @@ -1,3 +1,8 @@ +2007-06-28 Pedro Alves <ped...@po...> + + * PipeLib/PipeLib.h (SetPipeTag): Declare. + * PipeLib/PipeLib.cpp (SetPipeTag): Define. + 2007-06-24 Pedro Alves <ped...@po...> * conformtest.c: New file. Modified: trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp 2007-06-26 00:32:57 UTC (rev 1010) +++ trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp 2007-06-27 23:52:52 UTC (rev 1011) @@ -92,6 +92,17 @@ RegCloseKey (hk); } +/* Undocumented, for pipedev.dll debugging purposes only. */ +extern "C" BOOL +SetPipeTag (HANDLE p, const WCHAR* name) +{ + if (!DeviceIoControl (p, PIPE_IOCTL_SET_PIPE_TAG, + (LPVOID) name, (wcslen (name) + 1) * sizeof (WCHAR), + NULL, 0, NULL, NULL)) + return FALSE; + return TRUE; +} + static BOOL SetPipeName (HANDLE p, WCHAR* name) { Modified: trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h 2007-06-26 00:32:57 UTC (rev 1010) +++ trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h 2007-06-27 23:52:52 UTC (rev 1011) @@ -35,6 +35,9 @@ BOOL CreatePipe (PHANDLE,PHANDLE,LPSECURITY_ATTRIBUTES,DWORD); BOOL GetPipeName (HANDLE, WCHAR*); +/* Internal, for pipedev.dll debugging purposes. */ +BOOL SetPipeTag (HANDLE, const WCHAR*); + #ifdef __cplusplus } #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-27 23:55:02
|
Revision: 1012 http://svn.sourceforge.net/cegcc/?rev=1012&view=rev Author: pedroalves Date: 2007-06-27 16:55:01 -0700 (Wed, 27 Jun 2007) Log Message: ----------- * PipeDev/PipeDevice.h (PIPE_IOCTL_SET_PIPE_TAG): Define. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-27 23:52:52 UTC (rev 1011) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-27 23:55:01 UTC (rev 1012) @@ -2,6 +2,7 @@ * PipeLib/PipeLib.h (SetPipeTag): Declare. * PipeLib/PipeLib.cpp (SetPipeTag): Define. + * PipeDev/PipeDevice.h (PIPE_IOCTL_SET_PIPE_TAG): Define. 2007-06-24 Pedro Alves <ped...@po...> Modified: trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h 2007-06-27 23:52:52 UTC (rev 1011) +++ trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h 2007-06-27 23:55:01 UTC (rev 1012) @@ -36,6 +36,9 @@ #define PIPE_IOCTL_GET_PIPE_NAME \ CTL_CODE(FILE_DEVICE_STREAMS, 2049, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define PIPE_IOCTL_SET_PIPE_TAG \ + CTL_CODE(FILE_DEVICE_STREAMS, 2050, METHOD_BUFFERED, FILE_ANY_ACCESS) + #define DEVICE_DLL_NAME L"PipeDev.dll" #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-28 00:29:08
|
Revision: 1013 http://svn.sourceforge.net/cegcc/?rev=1013&view=rev Author: pedroalves Date: 2007-06-27 17:29:06 -0700 (Wed, 27 Jun 2007) Log Message: ----------- * PipeDev/PipeDevice.cpp (LogMessage2, LogMessage, LogScope) (LOG, LOGSCOPE): Move higher up in the file. (PipeDeviceContext::DeviceTag): New field. (PipeDeviceContext::TotalWritten, PipeDeviceContext::TotalRead) [DEBUG_MODE]: New fields. (PipeDeviceContext::~PipeDeviceContext): Free DeviceTag. (PipeDeviceContext::writeBytes(const void*, DWORD)): Change signature to ... (PipeDeviceContext::writeBytes(const BYTE*, DWORD)): ... this. Correct buffer wrapping. Add written bytes to TotalWritten. (PipeDeviceContext::readBytes(void*, DWORD)): Change signature to ... (PipeDeviceContext::readBytes(BYTE*, DWORD)): ... this. Correct buffer wrapping. Add read bytes to TotalRead. (LogThread) [DEBUG_MODE]: New function. (Init) [DEBUG_MODE]: Create a LogThread thread. Also set the AbortEvent event when OpenCount is 0. (Read(PipeOpenContext*, LPVOID, DWORD)): Change signature to ... (Read(PipeOpenContext*, BYTE*, DWORD)): ... this. Swap order of the wait events in the wait event array, so AbortEvent has priority. (Write(PipeOpenContext*, LPCVOID, DWORD)): Change signature to ... (Write(PipeOpenContext*, const BYTE*, DWORD)): ... this. Swap order of the wait events in the wait event array, so AbortEvent has priority. (IOControl): On PIPE_IOCTL_SET_PIPE_TAG ioctl, record the debug DeviceTag. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-27 23:55:01 UTC (rev 1012) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 00:29:06 UTC (rev 1013) @@ -1,5 +1,33 @@ 2007-06-28 Pedro Alves <ped...@po...> + * PipeDev/PipeDevice.cpp (LogMessage2, LogMessage, LogScope) + (LOG, LOGSCOPE): Move higher up in the file. + (PipeDeviceContext::DeviceTag): New field. + (PipeDeviceContext::TotalWritten, PipeDeviceContext::TotalRead) + [DEBUG_MODE]: New fields. + (PipeDeviceContext::~PipeDeviceContext): Free DeviceTag. + (PipeDeviceContext::writeBytes(const void*, DWORD)): Change signature + to ... + (PipeDeviceContext::writeBytes(const BYTE*, DWORD)): ... this. + Correct buffer wrapping. Add written bytes to TotalWritten. + (PipeDeviceContext::readBytes(void*, DWORD)): Change signature + to ... + (PipeDeviceContext::readBytes(BYTE*, DWORD)): ... this. + Correct buffer wrapping. Add read bytes to TotalRead. + (LogThread) [DEBUG_MODE]: New function. + (Init) [DEBUG_MODE]: Create a LogThread thread. Also set the + AbortEvent event when OpenCount is 0. + (Read(PipeOpenContext*, LPVOID, DWORD)): Change signature to ... + (Read(PipeOpenContext*, BYTE*, DWORD)): ... this. Swap order of the + wait events in the wait event array, so AbortEvent has priority. + (Write(PipeOpenContext*, LPCVOID, DWORD)): Change signature to ... + (Write(PipeOpenContext*, const BYTE*, DWORD)): ... this. Swap order + of the wait events in the wait event array, so AbortEvent has priority. + (IOControl): On PIPE_IOCTL_SET_PIPE_TAG ioctl, record the debug + DeviceTag. + +2007-06-28 Pedro Alves <ped...@po...> + * PipeLib/PipeLib.h (SetPipeTag): Declare. * PipeLib/PipeLib.cpp (SetPipeTag): Define. * PipeDev/PipeDevice.h (PIPE_IOCTL_SET_PIPE_TAG): Define. Modified: trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp 2007-06-27 23:55:01 UTC (rev 1012) +++ trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp 2007-06-28 00:29:06 UTC (rev 1013) @@ -64,6 +64,58 @@ # define G(CS) (CS) #endif +#ifdef DEBUG_MODE +static void +LogMessage2 (const char* msg) +{ + FILE* log = fopen ("pipelog.txt", "a+"); + fprintf (log, "%s", msg); + fclose (log); +} + +static void +LogMessage (const char *file, int line, const char* msg, ...) +{ + va_list ap; + char buf[1024]; + char *b = buf; + va_start (ap, msg); + sprintf (b, "%08x: %s (%d): ", (unsigned) GetCurrentThreadId (), file, line); + b += strlen (b); + vsprintf (b, msg, ap); + va_end (ap); + + LogMessage2 (buf); +} + +struct LogScope +{ + explicit LogScope (const char *func, const char* msg) + : func_(func) + , msg_(msg) + { + char buf[512]; + sprintf (buf, "> %s", msg_); + LogMessage (func_, -1, buf); + } + ~LogScope () + { + char buf[512]; + sprintf (buf, "< %s", msg_); + LogMessage (func_, -1, buf); + } + + const char* func_; + const char* msg_; +}; + +# define LOG(MSG, ...) LogMessage (__FUNCTION__, __LINE__, MSG, ## __VA_ARGS__) +# define LOGSCOPE(MSG) LogScope scope ## __LINE__(__FUNCTION__, MSG) +#else +# define LOG(MSG, ...) do; while (0) +# define LOGSCOPE(MSG) do; while (0) +#endif + class CSWrapper { public: @@ -251,7 +303,12 @@ : OpenCount(0) , WROpenCount(0) , DeviceName(NULL) + , DeviceTag(NULL) , Aborting(FALSE) +#ifdef DEBUG_MODE + , TotalWritten(0) + , TotalRead(0) +#endif , head(0) , count(0) { @@ -267,6 +324,8 @@ { if (DeviceName) free (DeviceName); + if (DeviceTag) + free (DeviceTag); if (ActivePath) free (ActivePath); CloseHandle (ReadEvent); @@ -294,29 +353,31 @@ cs.Unlock (); } - DWORD writeBytes (const void* data_, DWORD dsize) + DWORD writeBytes (const BYTE* data, DWORD dsize) { DWORD fit = sizeof (buffer) - size (); fit = min (dsize, fit); - const BYTE* data = (const BYTE*)data_; - BYTE* b = buffer + tail (); + DWORD t = tail (); for (DWORD i = 0; i < fit; i++) - b[i & (sizeof (buffer) - 1)] = data[i]; + buffer[(t + i) & (sizeof (buffer) - 1)] = data[i]; count += fit; +#ifdef DEBUG_MODE + TotalWritten += fit; +#endif return fit; } - DWORD readBytes (void* buf_, DWORD bsize) + DWORD readBytes (BYTE* buf, DWORD bsize) { - BYTE* buf = (BYTE*)buf_; DWORD fit = min (bsize, size ()); - - const BYTE* h = buffer + head; for (DWORD i = 0; i < fit; i++) - buf[i] = h[i & (sizeof (buffer) - 1)]; + buf[i] = buffer[(head + i) & (sizeof (buffer) - 1)]; count -= fit; head += fit; head &= (sizeof (buffer) - 1); +#ifdef DEBUG_MODE + TotalRead += fit; +#endif return fit; } @@ -331,8 +392,14 @@ HANDLE AbortEvent; WCHAR* DeviceName; + WCHAR* DeviceTag; BOOL Aborting; +#ifdef DEBUG_MODE + DWORD TotalWritten; + DWORD TotalRead; +#endif + private: BYTE buffer[0x1000]; DWORD head; @@ -377,58 +444,6 @@ return TRUE; } -#ifdef DEBUG_MODE -static void -LogMessage2 (const char* msg) -{ - FILE* log = fopen ("pipelog.txt", "a+"); - fprintf (log, "%s", msg); - fclose (log); -} - -static void -LogMessage (const char *file, int line, const char* msg, ...) -{ - va_list ap; - char buf[1024]; - char *b = buf; - va_start (ap, msg); - sprintf (b, "%08x: %s (%d): ", (unsigned) GetCurrentThreadId (), file, line); - b += strlen (b); - vsprintf (b, msg, ap); - va_end (ap); - - LogMessage2 (buf); -} - -struct LogScope -{ - explicit LogScope (const char *func, const char* msg) - : func_(func) - , msg_(msg) - { - char buf[512]; - sprintf (buf, "> %s", msg_); - LogMessage (func_, -1, buf); - } - ~LogScope () - { - char buf[512]; - sprintf (buf, "< %s", msg_); - LogMessage (func_, -1, buf); - } - - const char* func_; - const char* msg_; -}; - -# define LOG(MSG, ...) LogMessage (__FUNCTION__, __LINE__, MSG, ## __VA_ARGS__) -# define LOGSCOPE(MSG) LogScope scope ## __LINE__(__FUNCTION__, MSG) -#else -# define LOG(MSG, ...) do; while (0) -# define LOGSCOPE(MSG) do; while (0) -#endif - /* This is needed for MSVC, but it makes no harm in gcc. */ struct ltwstr { @@ -469,6 +484,41 @@ return hDev; } +#ifdef DEBUG_MODE + +static DWORD WINAPI +LogThread (void *arg) +{ + PipeDeviceContext* dev = (PipeDeviceContext*)arg; + + int count = 0; + + while (1) + switch (WaitForSingleObject (dev->AbortEvent, 1000)) + { + case WAIT_TIMEOUT: + { + PipeDeviceContext::LockGuard guard G(*dev); + LOG ("(%08d)\t" + "%ls\t" + "buffer size = %lu\t" + "read = %lu\t" + "write = %lu\n", + count++, + dev->DeviceTag ?: L"(notag)", + dev->size (), + dev->TotalRead, + dev->TotalWritten); + } + break; + default: + return 0; + } + + return 0; +} +#endif + PIPEDEV_API DWORD Init (LPCTSTR pContext) { @@ -489,6 +539,10 @@ if (pDeviceContext == NULL) return 0; +#ifdef DEBUG_MODE + CloseHandle (CreateThread (NULL, 0, LogThread, (void*)pDeviceContext, 0, NULL)); +#endif + open_pipes.insert (pContext); return (DWORD)pDeviceContext; @@ -506,9 +560,13 @@ the driver. */ #ifdef DEBUG_MODE - LOG ("oc %lu, wc: %lu, close_calls: %d\n", - dev->OpenCount, - dev->WROpenCount, close_calls); + if (pDeviceContext) + LOG ("oc %lu, wc: %lu, close_calls: %d\n", + pDeviceContext->OpenCount, + pDeviceContext->WROpenCount, + close_calls); + else + LOG ("close_calls: %d\n", close_calls); #endif if (pDeviceContext == NULL) @@ -611,16 +669,13 @@ return FALSE; dev->OpenCount--; - if (pOpenContext->dwAccessCode & GENERIC_WRITE) - { - dev->WROpenCount--; - if (dev->WROpenCount == 0) - /* Wake up the reading side so it can see - the broken pipe. */ - SetEvent (dev->AbortEvent); - } + dev->WROpenCount--; + if (dev->WROpenCount == 0 || dev->OpenCount == 0) + /* Wake up the other side so it can see the broken pipe. */ + SetEvent (dev->AbortEvent); + delete pOpenContext; LOG ("oc %lu, wc: %lu\n", @@ -628,9 +683,13 @@ if (dev->OpenCount == 0) { - /* Deactivating the device here seems to - corrupt the Device.exe, and sometimes hangs - the device. Do it in an auxilary thread. */ + /* Deactivating the device here seems to corrupt Device.exe, and + sometimes hangs the device. Do it in an auxilary thread. */ + /* Perhaps this should be made safer. If anotherthread was just + waken up due to the SetEvent above, this will be a race. + Perhaps we need a wait counter per device and have the + deactivator thread wait for it to reach 0 ... Irks, this is + getting fishy. */ DeactivatePipeDevice (dev); } @@ -638,18 +697,17 @@ } PIPEDEV_API DWORD -Read (PipeOpenContext* pOpenContext, LPVOID pBuffer_, DWORD dwCount) +Read (PipeOpenContext* pOpenContext, BYTE* pBuffer, DWORD dwCount) { LOGSCOPE ("\n"); - if (IsBadReadPtr (pBuffer_, dwCount)) + if (IsBadReadPtr (pBuffer, dwCount)) { SetLastError (ERROR_INVALID_PARAMETER); LOG ("\n"); return -1; } - BYTE* pBuffer = (BYTE*)pBuffer_; DWORD needed = dwCount; if (pOpenContext == NULL @@ -666,11 +724,13 @@ do { + LOG ("new iteration\n"); + { PipeDeviceContext::LockGuard guard G(*dev); - Events[0] = dev->WriteEvent; - Events[1] = dev->AbortEvent; + Events[0] = dev->AbortEvent; + Events[1] = dev->WriteEvent; /* Read before checking for broken pipe, so we get a chance to return valid data when that @@ -711,12 +771,15 @@ break; } + LOG ("going to wait for data\n"); + /* The buffer was empty, wait for data. */ switch (WaitForMultipleObjects (2, Events, FALSE, INFINITE)) { - case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: /* Data was written to the pipe. Do one more iteration to fetch what we can and bail out. */ + LOG ("write event detected\n"); breaknext = TRUE; break; default: @@ -733,18 +796,17 @@ } PIPEDEV_API DWORD -Write (PipeOpenContext* pOpenContext, LPCVOID pBuffer_, DWORD dwCount) +Write (PipeOpenContext* pOpenContext, const BYTE* pBuffer, DWORD dwCount) { LOGSCOPE ("\n"); - if (IsBadWritePtr ((void*) pBuffer_, dwCount)) + if (IsBadWritePtr ((void*) pBuffer, dwCount)) { SetLastError (ERROR_INVALID_PARAMETER); LOG ("\n"); return -1; } - const BYTE* pBuffer = (const BYTE*)pBuffer_; DWORD needed = dwCount; LOG ("oc %lu, wc: %lu\n", @@ -765,13 +827,15 @@ do { + LOG ("new iteration\n"); + { PipeDeviceContext::LockGuard guard G(*dev); LOG ("lock acquired\n"); - Events[0] = dev->ReadEvent; - Events[1] = dev->AbortEvent; + Events[0] = dev->AbortEvent; + Events[1] = dev->ReadEvent; if (dev->Aborting) { @@ -803,6 +867,8 @@ pBuffer += wrote; dwCount -= wrote; + LOG ("written %lu\n", wrote); + /* According to MSDN, a write of 0, also wakes the reading end of the pipe. */ PulseEvent (dev->WriteEvent); @@ -814,9 +880,11 @@ break; } + LOG ("going to wait for event\n"); switch (WaitForMultipleObjects (2, Events, FALSE, INFINITE)) { - case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: + LOG ("got read event\n"); breaknext = TRUE; break; default: @@ -828,7 +896,7 @@ } while (dwCount); - LOG ("%u\n", needed - dwCount); + LOG ("returning %u\n", needed - dwCount); return needed - dwCount; } @@ -883,6 +951,12 @@ switch (dwCode) { + case PIPE_IOCTL_SET_PIPE_TAG: + if (dev->DeviceTag) + free (dev->DeviceTag); + dev->DeviceTag = wcsdup ((WCHAR*)pBufIn); + bRet = TRUE; + break; case PIPE_IOCTL_SET_PIPE_NAME: if (dev->DeviceName) free (dev->DeviceName); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-28 00:34:06
|
Revision: 1014 http://svn.sourceforge.net/cegcc/?rev=1014&view=rev Author: pedroalves Date: 2007-06-27 17:34:03 -0700 (Wed, 27 Jun 2007) Log Message: ----------- * PipeDev/PipeDevice.cpp (FastCS): Delete. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 00:29:06 UTC (rev 1013) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 00:34:03 UTC (rev 1014) @@ -1,5 +1,9 @@ 2007-06-28 Pedro Alves <ped...@po...> + * PipeDev/PipeDevice.cpp (FastCS): Delete. + +2007-06-28 Pedro Alves <ped...@po...> + * PipeDev/PipeDevice.cpp (LogMessage2, LogMessage, LogScope) (LOG, LOGSCOPE): Move higher up in the file. (PipeDeviceContext::DeviceTag): New field. Modified: trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp 2007-06-28 00:29:06 UTC (rev 1013) +++ trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp 2007-06-28 00:34:03 UTC (rev 1014) @@ -157,47 +157,6 @@ CRITICAL_SECTION cs_; }; -class FastCS -{ -public: - FastCS () : Count(0) - { -#ifndef NOLOCKS - /* auto - only release one at a time. */ - EventHandle = CreateEvent (NULL, FALSE, FALSE, NULL); -#endif - } - ~FastCS () - { -#ifndef NOLOCKS - CloseHandle (EventHandle); -#endif - } - - void Lock () - { -#ifndef NOLOCKS - if (InterlockedIncrement (&Count) == 1) - /* first come - first serve. */ - return; - - /* everyone else, get in line. */ - WaitForSingleObject (EventHandle, INFINITE); -#endif - } - void Unlock () - { -#ifndef NOLOCKS - if (InterlockedDecrement (&Count) > 0) - /* release one pending */ - SetEvent (EventHandle); -#endif - } -private: - HANDLE EventHandle; - LONG Count; -}; - class RecursiveCS { public : This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-28 00:44:16
|
Revision: 1015 http://svn.sourceforge.net/cegcc/?rev=1015&view=rev Author: pedroalves Date: 2007-06-27 17:44:14 -0700 (Wed, 27 Jun 2007) Log Message: ----------- * PipeDev/PipeDevice.cpp (RecursiveCS): New implementation. (LockGuard): Better split the DEBUG_LOCKS version. (LockGuard::LockGuard) [DEBUG_LOCKS]: Prepend a "+" to the log output. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 00:34:03 UTC (rev 1014) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 00:44:14 UTC (rev 1015) @@ -1,5 +1,11 @@ 2007-06-28 Pedro Alves <ped...@po...> + * PipeDev/PipeDevice.cpp (RecursiveCS): New implementation. + (LockGuard): Better split the DEBUG_LOCKS version. + (LockGuard::LockGuard) [DEBUG_LOCKS]: Prepend a "+" to the log output. + +2007-06-28 Pedro Alves <ped...@po...> + * PipeDev/PipeDevice.cpp (FastCS): Delete. 2007-06-28 Pedro Alves <ped...@po...> Modified: trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp 2007-06-28 00:34:03 UTC (rev 1014) +++ trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp 2007-06-28 00:44:14 UTC (rev 1015) @@ -159,78 +159,85 @@ class RecursiveCS { -public : - RecursiveCS () - : Count(0) - , RecursionCount(0) - , ThreadID(0) + public: + RecursiveCS(); + ~RecursiveCS(); - { + void Lock(); + void Unlock(); + + private: + LONG Locks; + DWORD ThreadID; + DWORD Count; + HANDLE EventHandle; +}; + +RecursiveCS::RecursiveCS() + : Locks(0) + , ThreadID(0) + , Count(0) +{ #ifndef NOLOCKS - /* auto - only release one at a time. */ - EventHandle = CreateEvent (NULL, FALSE, FALSE, NULL); + /* auto - only release one at a time. */ + EventHandle = CreateEvent (NULL, FALSE, FALSE, NULL); #endif - } +} - ~RecursiveCS () - { +RecursiveCS::~RecursiveCS() +{ #ifndef NOLOCKS - CloseHandle (EventHandle); + CloseHandle (EventHandle); #endif - } +} - void Lock () - { +void +RecursiveCS::Lock() +{ #ifndef NOLOCKS - if (ThreadID == GetCurrentThreadId ()) - { - InterlockedIncrement (&RecursionCount); - return; - } + int test; + do + test = Locks; + while (InterlockedCompareExchange(&Locks, test + 1, test) != test); - if (InterlockedIncrement (&Count) == 1) - InterlockedExchange (&RecursionCount, 0); - else - WaitForSingleObject (EventHandle, INFINITE); + if (test != 0) + { + if (ThreadID != GetCurrentThreadId()) + { + /* Get in line */ + WaitForSingleObject (EventHandle, INFINITE); + } - ThreadID = GetCurrentThreadId (); + /* No need to wait anymore. */ + InterlockedDecrement (&Locks); + } + ThreadID = GetCurrentThreadId(); + ++Count; #endif - } - - void Unlock () - { +} + +void +RecursiveCS::Unlock() +{ #ifndef NOLOCKS - if (RecursionCount == 0) - { - if (InterlockedDecrement (&Count) > 0) - { - /* release one thread */ - SetEvent (EventHandle); - } - } - else - { - InterlockedDecrement (&RecursionCount); - } + if (!--Count) + { + ThreadID = 0; + + if (InterlockedCompareExchange (&Locks, 0, 1) != 1) + SetEvent (EventHandle); + } #endif - } +} -private: - HANDLE EventHandle; - LONG Count; - LONG RecursionCount; - DWORD ThreadID; -}; - - +#ifdef DEBUG_LOCKS template <class T> class LockGuard { public: -#ifdef DEBUG_LOCKS LockGuard (int line, T &cs) : cs_(cs), lineno(line) { - LOG ("LockGuard: line : %d\n", line); + LOG ("+LockGuard: line : %d\n", line); cs_.Lock (); } ~LockGuard () @@ -238,18 +245,24 @@ LOG ("~LockGuard: line : %d\n", lineno); cs_.Unlock (); } + +private: + T &cs_; + + int lineno; +}; #else +template <class T> +class LockGuard +{ +public: explicit LockGuard (T &cs) : cs_(cs) { cs_.Lock (); } ~LockGuard () { cs_.Unlock (); } -#endif private: T &cs_; - -#ifdef DEBUG_LOCKS - int lineno; +}; #endif -}; class PipeOpenContext; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-28 23:21:45
|
Revision: 1017 http://svn.sourceforge.net/cegcc/?rev=1017&view=rev Author: pedroalves Date: 2007-06-28 16:20:53 -0700 (Thu, 28 Jun 2007) Log Message: ----------- * PipeDev/PipeDevice.cpp : Move ... * PipeDev.cpp : ... here. Include PipeDev.h instead of PipeDevice.h. * PipeDev/PipeDevice.h : Move ... * PipeDev.h : ... here. * PipeDev/Makefile : Move ... * Makefile : ... here. (PipeDev_unstripped.dll): Depend on PipeDev.cpp and PipeDev.h. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog Added Paths: ----------- trunk/cegcc/tools/PipeLib/Makefile trunk/cegcc/tools/PipeLib/PipeDev.cpp trunk/cegcc/tools/PipeLib/PipeDev.h Removed Paths: ------------- trunk/cegcc/tools/PipeLib/PipeDev/Makefile trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 00:56:18 UTC (rev 1016) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 23:20:53 UTC (rev 1017) @@ -1,3 +1,13 @@ +2007-06-29 Pedro Alves <ped...@po...> + + * PipeDev/PipeDevice.cpp : Move ... + * PipeDev.cpp : ... here. Include PipeDev.h instead of PipeDevice.h. + * PipeDev/PipeDevice.h : Move ... + * PipeDev.h : ... here. + * PipeDev/Makefile : Move ... + * Makefile : ... here. + (PipeDev_unstripped.dll): Depend on PipeDev.cpp and PipeDev.h. + 2007-06-28 Pedro Alves <ped...@po...> * PipeDev/PipeDevice.cpp (RecursiveCS): New implementation. Copied: trunk/cegcc/tools/PipeLib/Makefile (from rev 1002, trunk/cegcc/tools/PipeLib/PipeDev/Makefile) =================================================================== --- trunk/cegcc/tools/PipeLib/Makefile (rev 0) +++ trunk/cegcc/tools/PipeLib/Makefile 2007-06-28 23:20:53 UTC (rev 1017) @@ -0,0 +1,27 @@ +TARGET=arm-wince-mingw32ce + +CXX=$(TARGET)-g++ +AR=$(TARGET)-ar +STRIP=$(TARGET)-strip + +WARNFLAGS=-Wall -Wextra + +INCLUDES= + +ALLFLAGS=$(INCLUDES) $(CXXFLAGS) $(WARNFLAGS) + +all: PipeDev.dll + +PipeDev_unstripped.dll: PipeDev.cpp PipeDev.h Makefile + $(CXX) $< -shared -o $@ $(ALLFLAGS) + +PipeDev.dll: PipeDev_unstripped.dll + $(STRIP) $< -o $@ + +download: PipeDev.dll + pcp PipeDev.dll ":/Windows/PipeDev.dll" + +clean: + rm -f PipeDev.dll + +.PHONY: all clean download Deleted: trunk/cegcc/tools/PipeLib/PipeDev/Makefile =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev/Makefile 2007-06-28 00:56:18 UTC (rev 1016) +++ trunk/cegcc/tools/PipeLib/PipeDev/Makefile 2007-06-28 23:20:53 UTC (rev 1017) @@ -1,27 +0,0 @@ -TARGET=arm-wince-mingw32ce - -CXX=$(TARGET)-g++ -AR=$(TARGET)-ar -STRIP=$(TARGET)-strip - -WARNFLAGS=-Wall -Wextra - -INCLUDES= - -ALLFLAGS=$(INCLUDES) $(CXXFLAGS) $(WARNFLAGS) - -all: PipeDev.dll - -PipeDev_unstripped.dll: PipeDevice.cpp Makefile - $(CXX) $< -shared -o $@ $(ALLFLAGS) - -PipeDev.dll: PipeDev_unstripped.dll - $(STRIP) $< -o $@ - -download: PipeDev.dll - pcp PipeDev.dll ":/Windows/PipeDev.dll" - -clean: - rm -f PipeDev.dll - -.PHONY: all clean download Deleted: trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp 2007-06-28 00:56:18 UTC (rev 1016) +++ trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp 2007-06-28 23:20:53 UTC (rev 1017) @@ -1,956 +0,0 @@ -/* Copyright (c) 2007, Pedro Alves - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -#include "PipeDevice.h" - -#include <windows.h> -#include <devload.h> -#include <set> -#include <string> - -#ifndef min -#define min(A, B) ((A) < (B) ? (A) : (B)) -#endif - -typedef struct _DEVICE_PSL_NOTIFY -{ - DWORD dwSize; - DWORD dwFlags; - HANDLE hProc; - HANDLE hThread; -} DEVICE_PSL_NOTIFY, *PDEVICE_PSL_NOTIFY; - -#ifndef FILE_DEVICE_PSL -#define FILE_DEVICE_PSL 259 -#endif - -#define IOCTL_PSL_NOTIFY \ - CTL_CODE (FILE_DEVICE_PSL, 255, METHOD_NEITHER, FILE_ANY_ACCESS) - -#define DLL_PROCESS_EXITING 4 - -#define PIPEDEV_API extern "C" __declspec (dllexport) - -//#define DEBUG_MODE -//#define NOLOCKS -//#define DEBUG_LOCKS - -#ifdef DEBUG_LOCKS -# define G(CS) (__LINE__, CS) -#else -# define G(CS) (CS) -#endif - -#ifdef DEBUG_MODE -static void -LogMessage2 (const char* msg) -{ - FILE* log = fopen ("pipelog.txt", "a+"); - fprintf (log, "%s", msg); - fclose (log); -} - -static void -LogMessage (const char *file, int line, const char* msg, ...) -{ - va_list ap; - char buf[1024]; - char *b = buf; - va_start (ap, msg); - sprintf (b, "%08x: %s (%d): ", (unsigned) GetCurrentThreadId (), file, line); - b += strlen (b); - vsprintf (b, msg, ap); - va_end (ap); - - LogMessage2 (buf); -} - -struct LogScope -{ - explicit LogScope (const char *func, const char* msg) - : func_(func) - , msg_(msg) - { - char buf[512]; - sprintf (buf, "> %s", msg_); - LogMessage (func_, -1, buf); - } - ~LogScope () - { - char buf[512]; - sprintf (buf, "< %s", msg_); - LogMessage (func_, -1, buf); - } - - const char* func_; - const char* msg_; -}; - -# define LOG(MSG, ...) LogMessage (__FUNCTION__, __LINE__, MSG, ## __VA_ARGS__) -# define LOGSCOPE(MSG) LogScope scope ## __LINE__(__FUNCTION__, MSG) -#else -# define LOG(MSG, ...) do; while (0) -# define LOGSCOPE(MSG) do; while (0) -#endif - -class CSWrapper -{ -public: - explicit CSWrapper (CRITICAL_SECTION* cs) : cs_(*cs) {} - ~CSWrapper () {} - - void Lock () - { -#ifndef NOLOCKS - EnterCriticalSection (&cs_); -#endif - } - void Unlock () - { -#ifndef NOLOCKS - LeaveCriticalSection (&cs_); -#endif - } -private: - CRITICAL_SECTION& cs_; -}; - -class CS : public CSWrapper -{ -public: - CS () : CSWrapper (&cs_) - { -#ifndef NOLOCKS - InitializeCriticalSection (&cs_); -#endif - } - ~CS () - { -#ifndef NOLOCKS - DeleteCriticalSection (&cs_); -#endif - } -private: - CRITICAL_SECTION cs_; -}; - -class RecursiveCS -{ - public: - RecursiveCS(); - ~RecursiveCS(); - - void Lock(); - void Unlock(); - - private: - LONG Locks; - DWORD ThreadID; - DWORD Count; - HANDLE EventHandle; -}; - -RecursiveCS::RecursiveCS() - : Locks(0) - , ThreadID(0) - , Count(0) -{ -#ifndef NOLOCKS - /* auto - only release one at a time. */ - EventHandle = CreateEvent (NULL, FALSE, FALSE, NULL); -#endif -} - -RecursiveCS::~RecursiveCS() -{ -#ifndef NOLOCKS - CloseHandle (EventHandle); -#endif -} - -void -RecursiveCS::Lock() -{ -#ifndef NOLOCKS - int test; - do - test = Locks; - while (InterlockedCompareExchange(&Locks, test + 1, test) != test); - - if (test != 0) - { - if (ThreadID != GetCurrentThreadId()) - { - /* Get in line */ - WaitForSingleObject (EventHandle, INFINITE); - } - - /* No need to wait anymore. */ - InterlockedDecrement (&Locks); - } - ThreadID = GetCurrentThreadId(); - ++Count; -#endif -} - -void -RecursiveCS::Unlock() -{ -#ifndef NOLOCKS - if (!--Count) - { - ThreadID = 0; - - if (InterlockedCompareExchange (&Locks, 0, 1) != 1) - SetEvent (EventHandle); - } -#endif -} - -#ifdef DEBUG_LOCKS -template <class T> -class LockGuard -{ -public: - LockGuard (int line, T &cs) : cs_(cs), lineno(line) - { - LOG ("+LockGuard: line : %d\n", line); - cs_.Lock (); - } - ~LockGuard () - { - LOG ("~LockGuard: line : %d\n", lineno); - cs_.Unlock (); - } - -private: - T &cs_; - - int lineno; -}; -#else -template <class T> -class LockGuard -{ -public: - explicit LockGuard (T &cs) : cs_(cs) { cs_.Lock (); } - ~LockGuard () { cs_.Unlock (); } - -private: - T &cs_; -}; -#endif - -class PipeOpenContext; - -class PipeDeviceContext -{ -public: - typedef ::LockGuard<PipeDeviceContext> LockGuard; - - explicit PipeDeviceContext (LPCWSTR activepath) - : OpenCount(0) - , WROpenCount(0) - , DeviceName(NULL) - , DeviceTag(NULL) - , Aborting(FALSE) -#ifdef DEBUG_MODE - , TotalWritten(0) - , TotalRead(0) -#endif - , head(0) - , count(0) - { - ActivePath = wcsdup (activepath); - ReadEvent = CreateEvent (NULL, FALSE, FALSE, NULL); - WriteEvent = CreateEvent (NULL, FALSE, FALSE, NULL); - - /* This should wake all threads, so it is manual reset. */ - AbortEvent = CreateEvent (NULL, TRUE, FALSE, NULL); - } - - ~PipeDeviceContext () - { - if (DeviceName) - free (DeviceName); - if (DeviceTag) - free (DeviceTag); - if (ActivePath) - free (ActivePath); - CloseHandle (ReadEvent); - CloseHandle (WriteEvent); - CloseHandle (AbortEvent); - } - - DWORD size () - { - return count; - } - - DWORD tail () - { - return (head + count) & (sizeof (buffer) - 1); - } - - void Lock () - { - cs.Lock (); - } - - void Unlock () - { - cs.Unlock (); - } - - DWORD writeBytes (const BYTE* data, DWORD dsize) - { - DWORD fit = sizeof (buffer) - size (); - fit = min (dsize, fit); - DWORD t = tail (); - for (DWORD i = 0; i < fit; i++) - buffer[(t + i) & (sizeof (buffer) - 1)] = data[i]; - count += fit; -#ifdef DEBUG_MODE - TotalWritten += fit; -#endif - return fit; - } - - DWORD readBytes (BYTE* buf, DWORD bsize) - { - DWORD fit = min (bsize, size ()); - for (DWORD i = 0; i < fit; i++) - buf[i] = buffer[(head + i) & (sizeof (buffer) - 1)]; - count -= fit; - head += fit; - head &= (sizeof (buffer) - 1); -#ifdef DEBUG_MODE - TotalRead += fit; -#endif - return fit; - } - -public: - DWORD OpenCount; - DWORD WROpenCount; - - WCHAR* ActivePath; - - HANDLE ReadEvent; - HANDLE WriteEvent; - HANDLE AbortEvent; - - WCHAR* DeviceName; - WCHAR* DeviceTag; - BOOL Aborting; - -#ifdef DEBUG_MODE - DWORD TotalWritten; - DWORD TotalRead; -#endif - -private: - BYTE buffer[0x1000]; - DWORD head; - DWORD count; - - RecursiveCS cs; -}; - -class PipeOpenContext -{ -public: - PipeOpenContext (PipeDeviceContext* devctx, - DWORD accessCode, DWORD shareMode) - : DeviceContext (devctx) - , dwAccessCode (accessCode) - , dwShareMode (shareMode) - {} - - ~PipeOpenContext () - {} - - PipeDeviceContext* DeviceContext; - DWORD dwAccessCode; - DWORD dwShareMode; -}; - -static CRITICAL_SECTION open_pipes_cs; - -extern "C" BOOL WINAPI -DllMain (HANDLE /*hinstDLL*/, DWORD dwReason, LPVOID /*lpvReserved*/) -{ - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - InitializeCriticalSection (&open_pipes_cs); - break; - case DLL_PROCESS_DETACH: - DeleteCriticalSection (&open_pipes_cs); - break; - } - - return TRUE; -} - -/* This is needed for MSVC, but it makes no harm in gcc. */ -struct ltwstr -{ - bool operator () (const std::wstring& s1, const std::wstring& s2) const - { - return wcscmp (s1.c_str (), s2.c_str ()) < 0; - } -}; - -typedef std::set<std::wstring, ltwstr> vwstring; -static vwstring open_pipes; - -PIPEDEV_API BOOL Deinit (PipeDeviceContext* pDeviceContext); - -static HANDLE -GetDeviceHandle (PipeDeviceContext* pDeviceContext) -{ - LOGSCOPE ("\n"); - HKEY hActive; - DWORD Type; - HANDLE hDev = INVALID_HANDLE_VALUE; - - DWORD status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, pDeviceContext->ActivePath, - 0, 0, &hActive); - if (status != ERROR_SUCCESS) - return INVALID_HANDLE_VALUE; - - DWORD Len = sizeof(hDev); - status = RegQueryValueEx (hActive, DEVLOAD_HANDLE_VALNAME, NULL, &Type, - (PUCHAR)&hDev, &Len); - if (status != ERROR_SUCCESS) - { - /* weird */ - } - - RegCloseKey (hActive); - - return hDev; -} - -#ifdef DEBUG_MODE - -static DWORD WINAPI -LogThread (void *arg) -{ - PipeDeviceContext* dev = (PipeDeviceContext*)arg; - - int count = 0; - - while (1) - switch (WaitForSingleObject (dev->AbortEvent, 1000)) - { - case WAIT_TIMEOUT: - { - PipeDeviceContext::LockGuard guard G(*dev); - LOG ("(%08d)\t" - "%ls\t" - "buffer size = %lu\t" - "read = %lu\t" - "write = %lu\n", - count++, - dev->DeviceTag ?: L"(notag)", - dev->size (), - dev->TotalRead, - dev->TotalWritten); - } - break; - default: - return 0; - } - - return 0; -} -#endif - -PIPEDEV_API DWORD -Init (LPCTSTR pContext) -{ - LOGSCOPE ("\n"); - CSWrapper cs (&open_pipes_cs); - LockGuard<CSWrapper> guard G(cs); - - LOG ("%ls\n", pContext); - - /* TODO: The key here isn't exactly the best. Maybe we should use - the device name instead, and get that from the registry - that would - also get rid of the IOCTL calls. */ - if (open_pipes.find (pContext) != open_pipes.end ()) - /* already open, PipeLib will try another one. */ - return 0; - - PipeDeviceContext* pDeviceContext = new PipeDeviceContext (pContext); - if (pDeviceContext == NULL) - return 0; - -#ifdef DEBUG_MODE - CloseHandle (CreateThread (NULL, 0, LogThread, (void*)pDeviceContext, 0, NULL)); -#endif - - open_pipes.insert (pContext); - - return (DWORD)pDeviceContext; -} - -#ifdef DEBUG_MODE -static int close_calls; -#endif - -PIPEDEV_API BOOL -Deinit (PipeDeviceContext* pDeviceContext) -{ - LOGSCOPE ("\n"); - /* All file handles must to be closed before deinitialising - the driver. */ - -#ifdef DEBUG_MODE - if (pDeviceContext) - LOG ("oc %lu, wc: %lu, close_calls: %d\n", - pDeviceContext->OpenCount, - pDeviceContext->WROpenCount, - close_calls); - else - LOG ("close_calls: %d\n", close_calls); -#endif - - if (pDeviceContext == NULL) - return FALSE; - - { - PipeDeviceContext::LockGuard guard G(*pDeviceContext); - - if (pDeviceContext->OpenCount != 0) - return FALSE; - } - - LOG ("deactivate success\n"); - - /* Allow reuse. */ - open_pipes.erase (pDeviceContext->ActivePath); - - /* Race? Is it possible that there can be another process - calling any function on the device while we are - Dinitializing it? Doesn't CE take care of that? */ - delete pDeviceContext; - return TRUE; -} - -PIPEDEV_API DWORD -Open (PipeDeviceContext* pDeviceContext, DWORD AccessCode, DWORD ShareMode) -{ - LOGSCOPE ("\n"); - - LOG ("oc %lu, wc: %lu, AccessCode %x, ShareMode %x\n", - pDeviceContext->OpenCount, pDeviceContext->WROpenCount, - AccessCode, ShareMode); - - PipeOpenContext* pOpenContext = - new PipeOpenContext (pDeviceContext, AccessCode, ShareMode); - - LOG ("going to lock\n"); - - PipeDeviceContext::LockGuard guard G(*pOpenContext->DeviceContext); - - LOG ("locked\n"); - - pDeviceContext->OpenCount++; - - if (AccessCode & GENERIC_WRITE) - pDeviceContext->WROpenCount++; - - LOG ("OpenCount: %lu, WROpenCount: %lu\n", - pDeviceContext->OpenCount, - pDeviceContext->WROpenCount); - - return (DWORD)pOpenContext; -} - -static DWORD WINAPI -Deactivator (HANDLE dev) -{ - LOGSCOPE ("\n"); - - if (!DeactivateDevice (dev)) - LOG("deactivate failed\n"); - else - LOG("deactivate success\n"); - - return 0; -} - -static void -DeactivatePipeDevice (PipeDeviceContext* dev) -{ - LOGSCOPE ("\n"); - HANDLE hdev = GetDeviceHandle (dev); - HANDLE h = CreateThread (NULL, 0, Deactivator, hdev, 0, NULL); - CloseHandle (h); -} - -PIPEDEV_API BOOL -Close (PipeOpenContext* pOpenContext) -{ - LOGSCOPE ("\n"); -#ifdef DEBUG_MODE - close_calls++; -#endif - - if (pOpenContext) - LOG ("oc %lu, wc: %lu\n", - pOpenContext->DeviceContext->OpenCount, - pOpenContext->DeviceContext->WROpenCount); - else - LOG ("openctx %p\n", pOpenContext); - - if (pOpenContext == NULL) - return FALSE; - - PipeDeviceContext* dev = pOpenContext->DeviceContext; - - PipeDeviceContext::LockGuard guard G(*dev); - - if (dev->OpenCount == 0) - return FALSE; - - dev->OpenCount--; - if (pOpenContext->dwAccessCode & GENERIC_WRITE) - dev->WROpenCount--; - - if (dev->WROpenCount == 0 || dev->OpenCount == 0) - /* Wake up the other side so it can see the broken pipe. */ - SetEvent (dev->AbortEvent); - - delete pOpenContext; - - LOG ("oc %lu, wc: %lu\n", - dev->OpenCount, dev->WROpenCount); - - if (dev->OpenCount == 0) - { - /* Deactivating the device here seems to corrupt Device.exe, and - sometimes hangs the device. Do it in an auxilary thread. */ - /* Perhaps this should be made safer. If anotherthread was just - waken up due to the SetEvent above, this will be a race. - Perhaps we need a wait counter per device and have the - deactivator thread wait for it to reach 0 ... Irks, this is - getting fishy. */ - DeactivatePipeDevice (dev); - } - - return TRUE; -} - -PIPEDEV_API DWORD -Read (PipeOpenContext* pOpenContext, BYTE* pBuffer, DWORD dwCount) -{ - LOGSCOPE ("\n"); - - if (IsBadReadPtr (pBuffer, dwCount)) - { - SetLastError (ERROR_INVALID_PARAMETER); - LOG ("\n"); - return -1; - } - - DWORD needed = dwCount; - - if (pOpenContext == NULL - || (pOpenContext->dwAccessCode & GENERIC_READ) == 0) - { - LOG ("Invalid access or no context\n"); - return (DWORD)-1; - } - - PipeDeviceContext* dev = pOpenContext->DeviceContext; - - BOOL breaknext = FALSE; - HANDLE Events[2]; - - do - { - LOG ("new iteration\n"); - - { - PipeDeviceContext::LockGuard guard G(*dev); - - Events[0] = dev->AbortEvent; - Events[1] = dev->WriteEvent; - - /* Read before checking for broken pipe, so - we get a chance to return valid data when that - happens. */ - DWORD read = dev->readBytes (pBuffer, dwCount); - pBuffer += read; - dwCount -= read; - - if (read) - SetEvent (dev->ReadEvent); - - if (dev->Aborting /* this device is long gone, */ - || dev->WROpenCount == 0 /* or broken pipe */ - || dev->OpenCount == 0 /* or, ... weird */ - ) - { - SetLastError (ERROR_BROKEN_PIPE); - if (needed - dwCount) - { - /* I don't know a way to report error and 'valid - data' at the same time. Is there a way? Instead - we report 'valid' and the next Read call will error. */ - LOG ("Pipe broken, but with data\n"); - break; - } - LOG ("Pipe broken\n"); - return (DWORD) -1; - } - - if (read || dwCount == 0) - { - /* We've either read something or pBuffer_ is full. */ - LOG ("read || dwCount == 0\n"); - break; - } - - if (breaknext) - break; - } - - LOG ("going to wait for data\n"); - - /* The buffer was empty, wait for data. */ - switch (WaitForMultipleObjects (2, Events, FALSE, INFINITE)) - { - case WAIT_OBJECT_0 + 1: - /* Data was written to the pipe. Do one more iteration - to fetch what we can and bail out. */ - LOG ("write event detected\n"); - breaknext = TRUE; - break; - default: - /* With either wait error or AbortEvent - signaled, return with error. */ - LOG ("WaitForMultipleObjects default case\n"); - return (DWORD) -1; - } - } - while (dwCount); - - LOG ("Read: %u\n", needed - dwCount); - return needed - dwCount; -} - -PIPEDEV_API DWORD -Write (PipeOpenContext* pOpenContext, const BYTE* pBuffer, DWORD dwCount) -{ - LOGSCOPE ("\n"); - - if (IsBadWritePtr ((void*) pBuffer, dwCount)) - { - SetLastError (ERROR_INVALID_PARAMETER); - LOG ("\n"); - return -1; - } - - DWORD needed = dwCount; - - LOG ("oc %lu, wc: %lu\n", - pOpenContext->DeviceContext->OpenCount, - pOpenContext->DeviceContext->WROpenCount); - - if (pOpenContext == NULL - || (pOpenContext->dwAccessCode & GENERIC_WRITE) == 0) - { - LOG ("Invalid access or no context\n"); - return (DWORD)-1; - } - - PipeDeviceContext* dev = pOpenContext->DeviceContext; - - BOOL breaknext = FALSE; - HANDLE Events[2]; - - do - { - LOG ("new iteration\n"); - - { - PipeDeviceContext::LockGuard guard G(*dev); - - LOG ("lock acquired\n"); - - Events[0] = dev->AbortEvent; - Events[1] = dev->ReadEvent; - - if (dev->Aborting) - { - /* this device is long gone */ - SetLastError (ERROR_NO_DATA); - LOG ("Device is gone\n"); - return (DWORD)-1; - } - - if (dev->OpenCount == 0) - { - /* weird */ - SetLastError (ERROR_NO_DATA); - LOG ("Device is not open\n"); - return (DWORD)-1; - } - - if (dev->OpenCount == dev->WROpenCount) - { - /* no readers */ - SetLastError (ERROR_NO_DATA); - LOG ("No readers left: oc %lu, wc: %lu\n", - dev->OpenCount, - dev->WROpenCount); - return (DWORD)-1; - } - - DWORD wrote = dev->writeBytes (pBuffer, dwCount); - pBuffer += wrote; - dwCount -= wrote; - - LOG ("written %lu\n", wrote); - - /* According to MSDN, a write of 0, also wakes - the reading end of the pipe. */ - PulseEvent (dev->WriteEvent); - - if (dwCount == 0) - break; - - if (breaknext) - break; - } - - LOG ("going to wait for event\n"); - switch (WaitForMultipleObjects (2, Events, FALSE, INFINITE)) - { - case WAIT_OBJECT_0 + 1: - LOG ("got read event\n"); - breaknext = TRUE; - break; - default: - /* With either wait error or AbortEvent - signaled, return with error. */ - LOG ("WaitForMultipleObjects default case\n"); - return (DWORD) -1; - } - } - while (dwCount); - - LOG ("returning %u\n", needed - dwCount); - return needed - dwCount; -} - -PIPEDEV_API DWORD -Seek (PipeOpenContext* /*pOpenContext*/, long /*Amount*/, WORD /*wType*/) -{ - LOGSCOPE ("\n"); - /* Pipes don't support seeking. */ - return (DWORD)-1; -} - -PIPEDEV_API BOOL -IOControl (PipeOpenContext* pOpenContext, DWORD dwCode, - PBYTE pBufIn, DWORD dwLenIn, - PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut) -{ - LOGSCOPE ("\n"); - - /* Kill unused warnings. */ - (void)pBufIn; - (void)dwLenIn; - (void)pBufOut; - (void)dwLenOut; - (void)pdwActualOut; - - BOOL bRet = FALSE; - - if (pOpenContext == NULL) - return FALSE; - - PipeDeviceContext* dev = pOpenContext->DeviceContext; - PipeDeviceContext::LockGuard guard G(*dev); - -#ifdef DEBUG_MODE - LOG ("%x : %d\n", dwCode, dev->OpenCount); -#endif - - if (dwCode == IOCTL_PSL_NOTIFY) - { - PDEVICE_PSL_NOTIFY pPslPacket = (PDEVICE_PSL_NOTIFY)pBufIn; - - if (pPslPacket->dwSize == sizeof (DEVICE_PSL_NOTIFY) - && pPslPacket->dwFlags == DLL_PROCESS_EXITING) - { - LOG ("Process dying: %p : %p\n", pPslPacket->hProc, pPslPacket->hThread); - dev->Aborting = TRUE; - /* Unlock all blocked threads. */ - SetEvent (dev->AbortEvent); - } - return TRUE; - } - - switch (dwCode) - { - case PIPE_IOCTL_SET_PIPE_TAG: - if (dev->DeviceTag) - free (dev->DeviceTag); - dev->DeviceTag = wcsdup ((WCHAR*)pBufIn); - bRet = TRUE; - break; - case PIPE_IOCTL_SET_PIPE_NAME: - if (dev->DeviceName) - free (dev->DeviceName); - dev->DeviceName = wcsdup ((WCHAR*)pBufIn); - bRet = TRUE; - break; - case PIPE_IOCTL_GET_PIPE_NAME: - wcscpy ( (WCHAR*)pBufOut, dev->DeviceName); - *pdwActualOut = (wcslen (dev->DeviceName) + 1) * sizeof (WCHAR); - bRet = TRUE; - break; - } - - return bRet; -} - -PIPEDEV_API void -PowerDown (PipeDeviceContext* /*pDeviceContext*/) -{ -} - -PIPEDEV_API void -PowerUp (PipeDeviceContext* /*pDeviceContext*/) -{ -} Deleted: trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h 2007-06-28 00:56:18 UTC (rev 1016) +++ trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h 2007-06-28 23:20:53 UTC (rev 1017) @@ -1,44 +0,0 @@ -/* Copyright (c) 2007, Pedro Alves - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -#ifndef __PIPEDEVICE_H__ -#define __PIPEDEVICE_H__ - -#include <windows.h> -#include <winioctl.h> - -#define PIPE_IOCTL_SET_PIPE_NAME \ - CTL_CODE(FILE_DEVICE_STREAMS, 2048, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define PIPE_IOCTL_GET_PIPE_NAME \ - CTL_CODE(FILE_DEVICE_STREAMS, 2049, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define PIPE_IOCTL_SET_PIPE_TAG \ - CTL_CODE(FILE_DEVICE_STREAMS, 2050, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define DEVICE_DLL_NAME L"PipeDev.dll" - -#endif Copied: trunk/cegcc/tools/PipeLib/PipeDev.cpp (from rev 1015, trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.cpp) =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev.cpp (rev 0) +++ trunk/cegcc/tools/PipeLib/PipeDev.cpp 2007-06-28 23:20:53 UTC (rev 1017) @@ -0,0 +1,956 @@ +/* Copyright (c) 2007, Pedro Alves + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "PipeDev.h" + +#include <windows.h> +#include <devload.h> +#include <set> +#include <string> + +#ifndef min +#define min(A, B) ((A) < (B) ? (A) : (B)) +#endif + +typedef struct _DEVICE_PSL_NOTIFY +{ + DWORD dwSize; + DWORD dwFlags; + HANDLE hProc; + HANDLE hThread; +} DEVICE_PSL_NOTIFY, *PDEVICE_PSL_NOTIFY; + +#ifndef FILE_DEVICE_PSL +#define FILE_DEVICE_PSL 259 +#endif + +#define IOCTL_PSL_NOTIFY \ + CTL_CODE (FILE_DEVICE_PSL, 255, METHOD_NEITHER, FILE_ANY_ACCESS) + +#define DLL_PROCESS_EXITING 4 + +#define PIPEDEV_API extern "C" __declspec (dllexport) + +//#define DEBUG_MODE +//#define NOLOCKS +//#define DEBUG_LOCKS + +#ifdef DEBUG_LOCKS +# define G(CS) (__LINE__, CS) +#else +# define G(CS) (CS) +#endif + +#ifdef DEBUG_MODE +static void +LogMessage2 (const char* msg) +{ + FILE* log = fopen ("pipelog.txt", "a+"); + fprintf (log, "%s", msg); + fclose (log); +} + +static void +LogMessage (const char *file, int line, const char* msg, ...) +{ + va_list ap; + char buf[1024]; + char *b = buf; + va_start (ap, msg); + sprintf (b, "%08x: %s (%d): ", (unsigned) GetCurrentThreadId (), file, line); + b += strlen (b); + vsprintf (b, msg, ap); + va_end (ap); + + LogMessage2 (buf); +} + +struct LogScope +{ + explicit LogScope (const char *func, const char* msg) + : func_(func) + , msg_(msg) + { + char buf[512]; + sprintf (buf, "> %s", msg_); + LogMessage (func_, -1, buf); + } + ~LogScope () + { + char buf[512]; + sprintf (buf, "< %s", msg_); + LogMessage (func_, -1, buf); + } + + const char* func_; + const char* msg_; +}; + +# define LOG(MSG, ...) LogMessage (__FUNCTION__, __LINE__, MSG, ## __VA_ARGS__) +# define LOGSCOPE(MSG) LogScope scope ## __LINE__(__FUNCTION__, MSG) +#else +# define LOG(MSG, ...) do; while (0) +# define LOGSCOPE(MSG) do; while (0) +#endif + +class CSWrapper +{ +public: + explicit CSWrapper (CRITICAL_SECTION* cs) : cs_(*cs) {} + ~CSWrapper () {} + + void Lock () + { +#ifndef NOLOCKS + EnterCriticalSection (&cs_); +#endif + } + void Unlock () + { +#ifndef NOLOCKS + LeaveCriticalSection (&cs_); +#endif + } +private: + CRITICAL_SECTION& cs_; +}; + +class CS : public CSWrapper +{ +public: + CS () : CSWrapper (&cs_) + { +#ifndef NOLOCKS + InitializeCriticalSection (&cs_); +#endif + } + ~CS () + { +#ifndef NOLOCKS + DeleteCriticalSection (&cs_); +#endif + } +private: + CRITICAL_SECTION cs_; +}; + +class RecursiveCS +{ + public: + RecursiveCS(); + ~RecursiveCS(); + + void Lock(); + void Unlock(); + + private: + LONG Locks; + DWORD ThreadID; + DWORD Count; + HANDLE EventHandle; +}; + +RecursiveCS::RecursiveCS() + : Locks(0) + , ThreadID(0) + , Count(0) +{ +#ifndef NOLOCKS + /* auto - only release one at a time. */ + EventHandle = CreateEvent (NULL, FALSE, FALSE, NULL); +#endif +} + +RecursiveCS::~RecursiveCS() +{ +#ifndef NOLOCKS + CloseHandle (EventHandle); +#endif +} + +void +RecursiveCS::Lock() +{ +#ifndef NOLOCKS + int test; + do + test = Locks; + while (InterlockedCompareExchange(&Locks, test + 1, test) != test); + + if (test != 0) + { + if (ThreadID != GetCurrentThreadId()) + { + /* Get in line */ + WaitForSingleObject (EventHandle, INFINITE); + } + + /* No need to wait anymore. */ + InterlockedDecrement (&Locks); + } + ThreadID = GetCurrentThreadId(); + ++Count; +#endif +} + +void +RecursiveCS::Unlock() +{ +#ifndef NOLOCKS + if (!--Count) + { + ThreadID = 0; + + if (InterlockedCompareExchange (&Locks, 0, 1) != 1) + SetEvent (EventHandle); + } +#endif +} + +#ifdef DEBUG_LOCKS +template <class T> +class LockGuard +{ +public: + LockGuard (int line, T &cs) : cs_(cs), lineno(line) + { + LOG ("+LockGuard: line : %d\n", line); + cs_.Lock (); + } + ~LockGuard () + { + LOG ("~LockGuard: line : %d\n", lineno); + cs_.Unlock (); + } + +private: + T &cs_; + + int lineno; +}; +#else +template <class T> +class LockGuard +{ +public: + explicit LockGuard (T &cs) : cs_(cs) { cs_.Lock (); } + ~LockGuard () { cs_.Unlock (); } + +private: + T &cs_; +}; +#endif + +class PipeOpenContext; + +class PipeDeviceContext +{ +public: + typedef ::LockGuard<PipeDeviceContext> LockGuard; + + explicit PipeDeviceContext (LPCWSTR activepath) + : OpenCount(0) + , WROpenCount(0) + , DeviceName(NULL) + , DeviceTag(NULL) + , Aborting(FALSE) +#ifdef DEBUG_MODE + , TotalWritten(0) + , TotalRead(0) +#endif + , head(0) + , count(0) + { + ActivePath = wcsdup (activepath); + ReadEvent = CreateEvent (NULL, FALSE, FALSE, NULL); + WriteEvent = CreateEvent (NULL, FALSE, FALSE, NULL); + + /* This should wake all threads, so it is manual reset. */ + AbortEvent = CreateEvent (NULL, TRUE, FALSE, NULL); + } + + ~PipeDeviceContext () + { + if (DeviceName) + free (DeviceName); + if (DeviceTag) + free (DeviceTag); + if (ActivePath) + free (ActivePath); + CloseHandle (ReadEvent); + CloseHandle (WriteEvent); + CloseHandle (AbortEvent); + } + + DWORD size () + { + return count; + } + + DWORD tail () + { + return (head + count) & (sizeof (buffer) - 1); + } + + void Lock () + { + cs.Lock (); + } + + void Unlock () + { + cs.Unlock (); + } + + DWORD writeBytes (const BYTE* data, DWORD dsize) + { + DWORD fit = sizeof (buffer) - size (); + fit = min (dsize, fit); + DWORD t = tail (); + for (DWORD i = 0; i < fit; i++) + buffer[(t + i) & (sizeof (buffer) - 1)] = data[i]; + count += fit; +#ifdef DEBUG_MODE + TotalWritten += fit; +#endif + return fit; + } + + DWORD readBytes (BYTE* buf, DWORD bsize) + { + DWORD fit = min (bsize, size ()); + for (DWORD i = 0; i < fit; i++) + buf[i] = buffer[(head + i) & (sizeof (buffer) - 1)]; + count -= fit; + head += fit; + head &= (sizeof (buffer) - 1); +#ifdef DEBUG_MODE + TotalRead += fit; +#endif + return fit; + } + +public: + DWORD OpenCount; + DWORD WROpenCount; + + WCHAR* ActivePath; + + HANDLE ReadEvent; + HANDLE WriteEvent; + HANDLE AbortEvent; + + WCHAR* DeviceName; + WCHAR* DeviceTag; + BOOL Aborting; + +#ifdef DEBUG_MODE + DWORD TotalWritten; + DWORD TotalRead; +#endif + +private: + BYTE buffer[0x1000]; + DWORD head; + DWORD count; + + RecursiveCS cs; +}; + +class PipeOpenContext +{ +public: + PipeOpenContext (PipeDeviceContext* devctx, + DWORD accessCode, DWORD shareMode) + : DeviceContext (devctx) + , dwAccessCode (accessCode) + , dwShareMode (shareMode) + {} + + ~PipeOpenContext () + {} + + PipeDeviceContext* DeviceContext; + DWORD dwAccessCode; + DWORD dwShareMode; +}; + +static CRITICAL_SECTION open_pipes_cs; + +extern "C" BOOL WINAPI +DllMain (HANDLE /*hinstDLL*/, DWORD dwReason, LPVOID /*lpvReserved*/) +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + InitializeCriticalSection (&open_pipes_cs); + break; + case DLL_PROCESS_DETACH: + DeleteCriticalSection (&open_pipes_cs); + break; + } + + return TRUE; +} + +/* This is needed for MSVC, but it makes no harm in gcc. */ +struct ltwstr +{ + bool operator () (const std::wstring& s1, const std::wstring& s2) const + { + return wcscmp (s1.c_str (), s2.c_str ()) < 0; + } +}; + +typedef std::set<std::wstring, ltwstr> vwstring; +static vwstring open_pipes; + +PIPEDEV_API BOOL Deinit (PipeDeviceContext* pDeviceContext); + +static HANDLE +GetDeviceHandle (PipeDeviceContext* pDeviceContext) +{ + LOGSCOPE ("\n"); + HKEY hActive; + DWORD Type; + HANDLE hDev = INVALID_HANDLE_VALUE; + + DWORD status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, pDeviceContext->ActivePath, + 0, 0, &hActive); + if (status != ERROR_SUCCESS) + return INVALID_HANDLE_VALUE; + + DWORD Len = sizeof(hDev); + status = RegQueryValueEx (hActive, DEVLOAD_HANDLE_VALNAME, NULL, &Type, + (PUCHAR)&hDev, &Len); + if (status != ERROR_SUCCESS) + { + /* weird */ + } + + RegCloseKey (hActive); + + return hDev; +} + +#ifdef DEBUG_MODE + +static DWORD WINAPI +LogThread (void *arg) +{ + PipeDeviceContext* dev = (PipeDeviceContext*)arg; + + int count = 0; + + while (1) + switch (WaitForSingleObject (dev->AbortEvent, 1000)) + { + case WAIT_TIMEOUT: + { + PipeDeviceContext::LockGuard guard G(*dev); + LOG ("(%08d)\t" + "%ls\t" + "buffer size = %lu\t" + "read = %lu\t" + "write = %lu\n", + count++, + dev->DeviceTag ?: L"(notag)", + dev->size (), + dev->TotalRead, + dev->TotalWritten); + } + break; + default: + return 0; + } + + return 0; +} +#endif + +PIPEDEV_API DWORD +Init (LPCTSTR pContext) +{ + LOGSCOPE ("\n"); + CSWrapper cs (&open_pipes_cs); + LockGuard<CSWrapper> guard G(cs); + + LOG ("%ls\n", pContext); + + /* TODO: The key here isn't exactly the best. Maybe we should use + the device name instead, and get that from the registry - that would + also get rid of the IOCTL calls. */ + if (open_pipes.find (pContext) != open_pipes.end ()) + /* already open, PipeLib will try another one. */ + return 0; + + PipeDeviceContext* pDeviceContext = new PipeDeviceContext (pContext); + if (pDeviceContext == NULL) + return 0; + +#ifdef DEBUG_MODE + CloseHandle (CreateThread (NULL, 0, LogThread, (void*)pDeviceContext, 0, NULL)); +#endif + + open_pipes.insert (pContext); + + return (DWORD)pDeviceContext; +} + +#ifdef DEBUG_MODE +static int close_calls; +#endif + +PIPEDEV_API BOOL +Deinit (PipeDeviceContext* pDeviceContext) +{ + LOGSCOPE ("\n"); + /* All file handles must to be closed before deinitialising + the driver. */ + +#ifdef DEBUG_MODE + if (pDeviceContext) + LOG ("oc %lu, wc: %lu, close_calls: %d\n", + pDeviceContext->OpenCount, + pDeviceContext->WROpenCount, + close_calls); + else + LOG ("close_calls: %d\n", close_calls); +#endif + + if (pDeviceContext == NULL) + return FALSE; + + { + PipeDeviceContext::LockGuard guard G(*pDeviceContext); + + if (pDeviceContext->OpenCount != 0) + return FALSE; + } + + LOG ("deactivate success\n"); + + /* Allow reuse. */ + open_pipes.erase (pDeviceContext->ActivePath); + + /* Race? Is it possible that there can be another process + calling any function on the device while we are + Dinitializing it? Doesn't CE take care of that? */ + delete pDeviceContext; + return TRUE; +} + +PIPEDEV_API DWORD +Open (PipeDeviceContext* pDeviceContext, DWORD AccessCode, DWORD ShareMode) +{ + LOGSCOPE ("\n"); + + LOG ("oc %lu, wc: %lu, AccessCode %x, ShareMode %x\n", + pDeviceContext->OpenCount, pDeviceContext->WROpenCount, + AccessCode, ShareMode); + + PipeOpenContext* pOpenContext = + new PipeOpenContext (pDeviceContext, AccessCode, ShareMode); + + LOG ("going to lock\n"); + + PipeDeviceContext::LockGuard guard G(*pOpenContext->DeviceContext); + + LOG ("locked\n"); + + pDeviceContext->OpenCount++; + + if (AccessCode & GENERIC_WRITE) + pDeviceContext->WROpenCount++; + + LOG ("OpenCount: %lu, WROpenCount: %lu\n", + pDeviceContext->OpenCount, + pDeviceContext->WROpenCount); + + return (DWORD)pOpenContext; +} + +static DWORD WINAPI +Deactivator (HANDLE dev) +{ + LOGSCOPE ("\n"); + + if (!DeactivateDevice (dev)) + LOG("deactivate failed\n"); + else + LOG("deactivate success\n"); + + return 0; +} + +static void +DeactivatePipeDevice (PipeDeviceContext* dev) +{ + LOGSCOPE ("\n"); + HANDLE hdev = GetDeviceHandle (dev); + HANDLE h = CreateThread (NULL, 0, Deactivator, hdev, 0, NULL); + CloseHandle (h); +} + +PIPEDEV_API BOOL +Close (PipeOpenContext* pOpenContext) +{ + LOGSCOPE ("\n"); +#ifdef DEBUG_MODE + close_calls++; +#endif + + if (pOpenContext) + LOG ("oc %lu, wc: %lu\n", + pOpenContext->DeviceContext->OpenCount, + pOpenContext->DeviceContext->WROpenCount); + else + LOG ("openctx %p\n", pOpenContext); + + if (pOpenContext == NULL) + return FALSE; + + PipeDeviceContext* dev = pOpenContext->DeviceContext; + + PipeDeviceContext::LockGuard guard G(*dev); + + if (dev->OpenCount == 0) + return FALSE; + + dev->OpenCount--; + if (pOpenContext->dwAccessCode & GENERIC_WRITE) + dev->WROpenCount--; + + if (dev->WROpenCount == 0 || dev->OpenCount == 0) + /* Wake up the other side so it can see the broken pipe. */ + SetEvent (dev->AbortEvent); + + delete pOpenContext; + + LOG ("oc %lu, wc: %lu\n", + dev->OpenCount, dev->WROpenCount); + + if (dev->OpenCount == 0) + { + /* Deactivating the device here seems to corrupt Device.exe, and + sometimes hangs the device. Do it in an auxilary thread. */ + /* Perhaps this should be made safer. If anotherthread was just + waken up due to the SetEvent above, this will be a race. + Perhaps we need a wait counter per device and have the + deactivator thread wait for it to reach 0 ... Irks, this is + getting fishy. */ + DeactivatePipeDevice (dev); + } + + return TRUE; +} + +PIPEDEV_API DWORD +Read (PipeOpenContext* pOpenContext, BYTE* pBuffer, DWORD dwCount) +{ + LOGSCOPE ("\n"); + + if (IsBadReadPtr (pBuffer, dwCount)) + { + SetLastError (ERROR_INVALID_PARAMETER); + LOG ("\n"); + return -1; + } + + DWORD needed = dwCount; + + if (pOpenContext == NULL + || (pOpenContext->dwAccessCode & GENERIC_READ) == 0) + { + LOG ("Invalid access or no context\n"); + return (DWORD)-1; + } + + PipeDeviceContext* dev = pOpenContext->DeviceContext; + + BOOL breaknext = FALSE; + HANDLE Events[2]; + + do + { + LOG ("new iteration\n"); + + { + PipeDeviceContext::LockGuard guard G(*dev); + + Events[0] = dev->AbortEvent; + Events[1] = dev->WriteEvent; + + /* Read before checking for broken pipe, so + we get a chance to return valid data when that + happens. */ + DWORD read = dev->readBytes (pBuffer, dwCount); + pBuffer += read; + dwCount -= read; + + if (read) + SetEvent (dev->ReadEvent); + + if (dev->Aborting /* this device is long gone, */ + || dev->WROpenCount == 0 /* or broken pipe */ + || dev->OpenCount == 0 /* or, ... weird */ + ) + { + SetLastError (ERROR_BROKEN_PIPE); + if (needed - dwCount) + { + /* I don't know a way to report error and 'valid + data' at the same time. Is there a way? Instead + we report 'valid' and the next Read call will error. */ + LOG ("Pipe broken, but with data\n"); + break; + } + LOG ("Pipe broken\n"); + return (DWORD) -1; + } + + if (read || dwCount == 0) + { + /* We've either read something or pBuffer_ is full. */ + LOG ("read || dwCount == 0\n"); + break; + } + + if (breaknext) + break; + } + + LOG ("going to wait for data\n"); + + /* The buffer was empty, wait for data. */ + switch (WaitForMultipleObjects (2, Events, FALSE, INFINITE)) + { + case WAIT_OBJECT_0 + 1: + /* Data was written to the pipe. Do one more iteration + to fetch what we can and bail out. */ + LOG ("write event detected\n"); + breaknext = TRUE; + break; + default: + /* With either wait error or AbortEvent + signaled, return with error. */ + LOG ("WaitForMultipleObjects default case\n"); + return (DWORD) -1; + } + } + while (dwCount); + + LOG ("Read: %u\n", needed - dwCount); + return needed - dwCount; +} + +PIPEDEV_API DWORD +Write (PipeOpenContext* pOpenContext, const BYTE* pBuffer, DWORD dwCount) +{ + LOGSCOPE ("\n"); + + if (IsBadWritePtr ((void*) pBuffer, dwCount)) + { + SetLastError (ERROR_INVALID_PARAMETER); + LOG ("\n"); + return -1; + } + + DWORD needed = dwCount; + + LOG ("oc %lu, wc: %lu\n", + pOpenContext->DeviceContext->OpenCount, + pOpenContext->DeviceContext->WROpenCount); + + if (pOpenContext == NULL + || (pOpenContext->dwAccessCode & GENERIC_WRITE) == 0) + { + LOG ("Invalid access or no context\n"); + return (DWORD)-1; + } + + PipeDeviceContext* dev = pOpenContext->DeviceContext; + + BOOL breaknext = FALSE; + HANDLE Events[2]; + + do + { + LOG ("new iteration\n"); + + { + PipeDeviceContext::LockGuard guard G(*dev); + + LOG ("lock acquired\n"); + + Events[0] = dev->AbortEvent; + Events[1] = dev->ReadEvent; + + if (dev->Aborting) + { + /* this device is long gone */ + SetLastError (ERROR_NO_DATA); + LOG ("Device is gone\n"); + return (DWORD)-1; + } + + if (dev->OpenCount == 0) + { + /* weird */ + SetLastError (ERROR_NO_DATA); + LOG ("Device is not open\n"); + return (DWORD)-1; + } + + if (dev->OpenCount == dev->WROpenCount) + { + /* no readers */ + SetLastError (ERROR_NO_DATA); + LOG ("No readers left: oc %lu, wc: %lu\n", + dev->OpenCount, + dev->WROpenCount); + return (DWORD)-1; + } + + DWORD wrote = dev->writeBytes (pBuffer, dwCount); + pBuffer += wrote; + dwCount -= wrote; + + LOG ("written %lu\n", wrote); + + /* According to MSDN, a write of 0, also wakes + the reading end of the pipe. */ + PulseEvent (dev->WriteEvent); + + if (dwCount == 0) + break; + + if (breaknext) + break; + } + + LOG ("going to wait for event\n"); + switch (WaitForMultipleObjects (2, Events, FALSE, INFINITE)) + { + case WAIT_OBJECT_0 + 1: + LOG ("got read event\n"); + breaknext = TRUE; + break; + default: + /* With either wait error or AbortEvent + signaled, return with error. */ + LOG ("WaitForMultipleObjects default case\n"); + return (DWORD) -1; + } + } + while (dwCount); + + LOG ("returning %u\n", needed - dwCount); + return needed - dwCount; +} + +PIPEDEV_API DWORD +Seek (PipeOpenContext* /*pOpenContext*/, long /*Amount*/, WORD /*wType*/) +{ + LOGSCOPE ("\n"); + /* Pipes don't support seeking. */ + return (DWORD)-1; +} + +PIPEDEV_API BOOL +IOControl (PipeOpenContext* pOpenContext, DWORD dwCode, + PBYTE pBufIn, DWORD dwLenIn, + PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut) +{ + LOGSCOPE ("\n"); + + /* Kill unused warnings. */ + (void)pBufIn; + (void)dwLenIn; + (void)pBufOut; + (void)dwLenOut; + (void)pdwActualOut; + + BOOL bRet = FALSE; + + if (pOpenContext == NULL) + return FALSE; + + PipeDeviceContext* dev = pOpenContext->DeviceContext; + PipeDeviceContext::LockGuard guard G(*dev); + +#ifdef DEBUG_MODE + LOG ("%x : %d\n", dwCode, dev->OpenCount); +#endif + + if (dwCode == IOCTL_PSL_NOTIFY) + { + PDEVICE_PSL_NOTIFY pPslPacket = (PDEVICE_PSL_NOTIFY)pBufIn; + + if (pPslPacket->dwSize == sizeof (DEVICE_PSL_NOTIFY) + && pPslPacket->dwFlags == DLL_PROCESS_EXITING) + { + LOG ("Process dying: %p : %p\n", pPslPacket->hProc, pPslPacket->hThread); + dev->Aborting = TRUE; + /* Unlock all blocked threads. */ + SetEvent (dev->AbortEvent); + } + return TRUE; + } + + switch (dwCode) + { + case PIPE_IOCTL_SET_PIPE_TAG: + if (dev->DeviceTag) + free (dev->DeviceTag); + dev->DeviceTag = wcsdup ((WCHAR*)pBufIn); + bRet = TRUE; + break; + case PIPE_IOCTL_SET_PIPE_NAME: + if (dev->DeviceName) + free (dev->DeviceName); + dev->DeviceName = wcsdup ((WCHAR*)pBufIn); + bRet = TRUE; + break; + case PIPE_IOCTL_GET_PIPE_NAME: + wcscpy ( (WCHAR*)pBufOut, dev->DeviceName); + *pdwActualOut = (wcslen (dev->DeviceName) + 1) * sizeof (WCHAR); + bRet = TRUE; + break; + } + + return bRet; +} + +PIPEDEV_API void +PowerDown (PipeDeviceContext* /*pDeviceContext*/) +{ +} + +PIPEDEV_API void +PowerUp (PipeDeviceContext* /*pDeviceContext*/) +{ +} Copied: trunk/cegcc/tools/PipeLib/PipeDev.h (from rev 1012, trunk/cegcc/tools/PipeLib/PipeDev/PipeDevice.h) =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev.h (rev 0) +++ trunk/cegcc/tools/PipeLib/PipeDev.h 2007-06-28 23:20:53 UTC (rev 1017) @@ -0,0 +1,44 @@ +/* Copyright (c) 2007, Pedro Alves + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#ifndef __PIPEDEVICE_H__ +#define __PIPEDEVICE_H__ + +#include <windows.h> +#include <winioctl.h> + +#define PIPE_IOCTL_SET_PIPE_NAME \ + CTL_CODE(FILE_DEVICE_STREAMS, 2048, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define PIPE_IOCTL_GET_PIPE_NAME \ + CTL_CODE(FILE_DEVICE_STREAMS, 2049, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define PIPE_IOCTL_SET_PIPE_TAG \ + CTL_CODE(FILE_DEVICE_STREAMS, 2050, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define DEVICE_DLL_NAME L"PipeDev.dll" + +#endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-28 23:31:23
|
Revision: 1018 http://svn.sourceforge.net/cegcc/?rev=1018&view=rev Author: pedroalves Date: 2007-06-28 16:31:21 -0700 (Thu, 28 Jun 2007) Log Message: ----------- * PipeLib/PipeLib.cpp : Move ... * PipeLib.cpp : ... here. Include PipeDev.h instead of PipeDevice.h. * PipeLib/PipeLib.h : Move ... * PipeLib.h : ... here. * PipeDev/Makefile : Delete. * Makefile (all): Add libPipeLib.a. (PipeLib.o, libPipeLib.a, clean-dev, clean-lib): New rules. (clean): Depend on clean-dev and clean-lib to do the clean work. (.PHONY): Add clean-dev and clean-lib. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog trunk/cegcc/tools/PipeLib/Makefile Added Paths: ----------- trunk/cegcc/tools/PipeLib/PipeLib.cpp trunk/cegcc/tools/PipeLib/PipeLib.h Removed Paths: ------------- trunk/cegcc/tools/PipeLib/PipeLib/Makefile trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 23:20:53 UTC (rev 1017) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 23:31:21 UTC (rev 1018) @@ -1,5 +1,17 @@ 2007-06-29 Pedro Alves <ped...@po...> + * PipeLib/PipeLib.cpp : Move ... + * PipeLib.cpp : ... here. Include PipeDev.h instead of PipeDevice.h. + * PipeLib/PipeLib.h : Move ... + * PipeLib.h : ... here. + * PipeDev/Makefile : Delete. + * Makefile (all): Add libPipeLib.a. + (PipeLib.o, libPipeLib.a, clean-dev, clean-lib): New rules. + (clean): Depend on clean-dev and clean-lib to do the clean work. + (.PHONY): Add clean-dev and clean-lib. + +2007-06-29 Pedro Alves <ped...@po...> + * PipeDev/PipeDevice.cpp : Move ... * PipeDev.cpp : ... here. Include PipeDev.h instead of PipeDevice.h. * PipeDev/PipeDevice.h : Move ... Modified: trunk/cegcc/tools/PipeLib/Makefile =================================================================== --- trunk/cegcc/tools/PipeLib/Makefile 2007-06-28 23:20:53 UTC (rev 1017) +++ trunk/cegcc/tools/PipeLib/Makefile 2007-06-28 23:31:21 UTC (rev 1018) @@ -10,7 +10,7 @@ ALLFLAGS=$(INCLUDES) $(CXXFLAGS) $(WARNFLAGS) -all: PipeDev.dll +all: PipeDev.dll libPipeLib.a PipeDev_unstripped.dll: PipeDev.cpp PipeDev.h Makefile $(CXX) $< -shared -o $@ $(ALLFLAGS) @@ -18,10 +18,22 @@ PipeDev.dll: PipeDev_unstripped.dll $(STRIP) $< -o $@ +PipeLib.o: PipeLib.cpp + $(CXX) $< -c -o $@ $(ALLFLAGS) + +libPipeLib.a: PipeLib.o + rm -f $@ + $(AR) r $@ $< + download: PipeDev.dll pcp PipeDev.dll ":/Windows/PipeDev.dll" -clean: - rm -f PipeDev.dll +clean-dev: + rm -f PipeDev.dll PipeDev_unstripped.dll -.PHONY: all clean download +clean-lib: + rm -f libPipeLib.a PipeLib.o + +clean: clean-dev clean-lib + +.PHONY: all clean clean-dev clean-lib download Deleted: trunk/cegcc/tools/PipeLib/PipeLib/Makefile =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib/Makefile 2007-06-28 23:20:53 UTC (rev 1017) +++ trunk/cegcc/tools/PipeLib/PipeLib/Makefile 2007-06-28 23:31:21 UTC (rev 1018) @@ -1,22 +0,0 @@ -TARGET=arm-wince-mingw32ce - -CXX=$(TARGET)-g++ -AR=$(TARGET)-ar - -INCLUDES=-I../PipeDev/ - -ALLFLAGS=$(INCLUDES) $(CXXFLAGS) - -all: libPipeLib.a - -PipeLib.o: PipeLib.cpp - $(CXX) $< -c -o $@ $(ALLFLAGS) - -libPipeLib.a: PipeLib.o - rm -f $@ - $(AR) r $@ $< - -clean: - rm -f libPipeLib.a PipeLib.o - -.PHONE: all clean Deleted: trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp 2007-06-28 23:20:53 UTC (rev 1017) +++ trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp 2007-06-28 23:31:21 UTC (rev 1018) @@ -1,229 +0,0 @@ -/* Copyright (c) 2007, Pedro Alves - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -#include <PipeDevice.h> - -#include <windows.h> -#include <devload.h> -#include <stdlib.h> - -#define KEY_NAME_BASE L"PipeDevice_" -#define NAME_BASE L"PD" /* Pipe Device */ -#define MAX_INSTANCES 99 - -#if 0 - -/* Doesn't work on CE < 5 ... */ -static int -FindFreeInstanceIndex (void) -{ - HANDLE h; - DEVMGR_DEVICE_INFORMATION di; - WCHAR wzName[6]; - for (int i=0; i < MAX_INSTANCES; i++) - { - wsprintf (wzName, L"%s%02d:", NAME_BASE, i); - di.dwSize = sizeof (di); - h = FindFirstDevice (DeviceSearchByLegacyName, wzName, &di); - if (h == INVALID_HANDLE_VALUE) - return i; - CloseHandle (h); - } - return -1; -} -#endif - -static void -PrepareRegistryForInstance (DWORD dwIndex, WCHAR** wzKey) -{ - DWORD dw; - HKEY hk; - WCHAR szKeyName[255]; - WCHAR wzPrefix[4]; //3 letter + zero character - DWORD dwDisp; - swprintf (wzPrefix, L"%s%d", NAME_BASE, dwIndex / 10); - - swprintf (szKeyName, L"Drivers\\%s%d", KEY_NAME_BASE, dwIndex); - *wzKey = wcsdup (szKeyName); - - if (ERROR_SUCCESS != RegCreateKeyEx (HKEY_LOCAL_MACHINE, - szKeyName, 0, NULL, 0, - KEY_WRITE, NULL, &hk, &dwDisp)) - { - wprintf (L"Failed to create registry key %s, error = %d\n", - szKeyName, (int) GetLastError ()); - return; - } - - RegSetValueEx (hk, L"dll", 0, REG_SZ, (BYTE *)DEVICE_DLL_NAME, - sizeof (DEVICE_DLL_NAME)); - RegSetValueEx (hk, L"prefix", 0, REG_SZ, (BYTE *)wzPrefix, - sizeof (wzPrefix)); - - dw = dwIndex % 10; - RegSetValueEx (hk, L"index", 0, REG_DWORD, (BYTE *)&dw, sizeof (dw)); - - dw = DEVFLAGS_LOADLIBRARY | DEVFLAGS_NAKEDENTRIES; - RegSetValueEx (hk, L"Flags", 0, REG_DWORD, (BYTE *)&dw, sizeof (dw)); - - RegCloseKey (hk); -} - -/* Undocumented, for pipedev.dll debugging purposes only. */ -extern "C" BOOL -SetPipeTag (HANDLE p, const WCHAR* name) -{ - if (!DeviceIoControl (p, PIPE_IOCTL_SET_PIPE_TAG, - (LPVOID) name, (wcslen (name) + 1) * sizeof (WCHAR), - NULL, 0, NULL, NULL)) - return FALSE; - return TRUE; -} - -static BOOL -SetPipeName (HANDLE p, WCHAR* name) -{ - if (!DeviceIoControl (p, PIPE_IOCTL_SET_PIPE_NAME, - (LPVOID) name, (wcslen (name) + 1) * sizeof (WCHAR), - NULL, 0, NULL, NULL)) - return FALSE; - return TRUE; -} - -extern "C" BOOL -GetPipeName (HANDLE p, WCHAR* name) -{ - DWORD actual; - if (!DeviceIoControl (p, PIPE_IOCTL_GET_PIPE_NAME, - NULL, 0, - (LPVOID)name, MAX_PATH * sizeof (WCHAR), - &actual, NULL)) - return FALSE; - return TRUE; -} - -extern "C" BOOL -CreatePipe (PHANDLE hReadPipe, - PHANDLE hWritePipe, - LPSECURITY_ATTRIBUTES lpPipeAttributes, - DWORD nSize) -{ - int inst; - WCHAR* wsKey; - HANDLE h; - - *hReadPipe = NULL; - *hWritePipe = NULL; - - for (inst = 0 ; inst < MAX_INSTANCES; inst++) - { - PrepareRegistryForInstance (inst, &wsKey); - h = ActivateDevice (wsKey, 0); - RegDeleteKey (HKEY_LOCAL_MACHINE, wsKey); - free (wsKey); - - /* Although MSDN documentcs that error should - return INVALID_HANDLE_VALUE, I see it returning - NULL here. */ - if (h != INVALID_HANDLE_VALUE && h != NULL) - break; - } - - if (inst == MAX_INSTANCES) - return FALSE; - - /* name + num + ':' + '0' */ - wchar_t device_name[(sizeof (NAME_BASE) - 1) + 2 + 1 + 1]; - wsprintf (device_name, L"%s%02d:", NAME_BASE, inst); - - *hReadPipe = CreateFile (device_name, - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - - SetPipeName (*hReadPipe, device_name); - - *hWritePipe = CreateFile (device_name, - GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - - return TRUE; -} - -#if 0 - -struct PeekStruct -{ - DWORD Size; /* for future extension */ - PVOID lpBuffer, - DWORD nBufferSize, - - /* TODO: We need to use MapPtr for this to work */ - LPDWORD lpBytesRead, - LPDWORD lpTotalBytesAvail, - LPDWORD lpBytesLeftThisMessage - }; - -BOOL -PeekNamedPipe (HANDLE hNamedPipe, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesRead, - LPDWORD lpTotalBytesAvail, - LPDWORD lpBytesLeftThisMessage - ) -{ - DWORD avail; - DWORD actual; - - PeekStruct data; - data.Size = sizeof (PeekStruct); - data.lpBuffer = lpBuffer; - data.nBufferSize = nBufferSize; - data.lpBytesRead = lpBytesRead; - data.lpTotalBytesAvail = lpTotalBytesAvail; - data.lpBytesLeftThisMessage = lpBytesLeftThisMessage; - - if (!DeviceIoControl (hNamedPipe, PIPE_IOCTRL_PEEK_NAMED_PIPE, - NULL, 0, - (LPVOID)&data, sizeof (PeekStruct), &actual, NULL)) - return FALSE; - - /* We can detect here if we are talking to an older driver. */ - if (actual != data.Size) - return FALSE; - - return FALSE; -} - -#endif Deleted: trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h 2007-06-28 23:20:53 UTC (rev 1017) +++ trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h 2007-06-28 23:31:21 UTC (rev 1018) @@ -1,46 +0,0 @@ -/* Copyright (c) 2007, Pedro Alves - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -#ifndef __PIPE_LIB_H__ -#define __PIPE_LIB_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -BOOL CreatePipe (PHANDLE,PHANDLE,LPSECURITY_ATTRIBUTES,DWORD); -BOOL GetPipeName (HANDLE, WCHAR*); - -/* Internal, for pipedev.dll debugging purposes. */ -BOOL SetPipeTag (HANDLE, const WCHAR*); - -#ifdef __cplusplus -} -#endif - - -#endif Copied: trunk/cegcc/tools/PipeLib/PipeLib.cpp (from rev 1011, trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.cpp) =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib.cpp (rev 0) +++ trunk/cegcc/tools/PipeLib/PipeLib.cpp 2007-06-28 23:31:21 UTC (rev 1018) @@ -0,0 +1,229 @@ +/* Copyright (c) 2007, Pedro Alves + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "PipeDev.h" + +#include <windows.h> +#include <devload.h> +#include <stdlib.h> + +#define KEY_NAME_BASE L"PipeDevice_" +#define NAME_BASE L"PD" /* Pipe Device */ +#define MAX_INSTANCES 99 + +#if 0 + +/* Doesn't work on CE < 5 ... */ +static int +FindFreeInstanceIndex (void) +{ + HANDLE h; + DEVMGR_DEVICE_INFORMATION di; + WCHAR wzName[6]; + for (int i=0; i < MAX_INSTANCES; i++) + { + wsprintf (wzName, L"%s%02d:", NAME_BASE, i); + di.dwSize = sizeof (di); + h = FindFirstDevice (DeviceSearchByLegacyName, wzName, &di); + if (h == INVALID_HANDLE_VALUE) + return i; + CloseHandle (h); + } + return -1; +} +#endif + +static void +PrepareRegistryForInstance (DWORD dwIndex, WCHAR** wzKey) +{ + DWORD dw; + HKEY hk; + WCHAR szKeyName[255]; + WCHAR wzPrefix[4]; //3 letter + zero character + DWORD dwDisp; + swprintf (wzPrefix, L"%s%d", NAME_BASE, dwIndex / 10); + + swprintf (szKeyName, L"Drivers\\%s%d", KEY_NAME_BASE, dwIndex); + *wzKey = wcsdup (szKeyName); + + if (ERROR_SUCCESS != RegCreateKeyEx (HKEY_LOCAL_MACHINE, + szKeyName, 0, NULL, 0, + KEY_WRITE, NULL, &hk, &dwDisp)) + { + wprintf (L"Failed to create registry key %s, error = %d\n", + szKeyName, (int) GetLastError ()); + return; + } + + RegSetValueEx (hk, L"dll", 0, REG_SZ, (BYTE *)DEVICE_DLL_NAME, + sizeof (DEVICE_DLL_NAME)); + RegSetValueEx (hk, L"prefix", 0, REG_SZ, (BYTE *)wzPrefix, + sizeof (wzPrefix)); + + dw = dwIndex % 10; + RegSetValueEx (hk, L"index", 0, REG_DWORD, (BYTE *)&dw, sizeof (dw)); + + dw = DEVFLAGS_LOADLIBRARY | DEVFLAGS_NAKEDENTRIES; + RegSetValueEx (hk, L"Flags", 0, REG_DWORD, (BYTE *)&dw, sizeof (dw)); + + RegCloseKey (hk); +} + +/* Undocumented, for pipedev.dll debugging purposes only. */ +extern "C" BOOL +SetPipeTag (HANDLE p, const WCHAR* name) +{ + if (!DeviceIoControl (p, PIPE_IOCTL_SET_PIPE_TAG, + (LPVOID) name, (wcslen (name) + 1) * sizeof (WCHAR), + NULL, 0, NULL, NULL)) + return FALSE; + return TRUE; +} + +static BOOL +SetPipeName (HANDLE p, WCHAR* name) +{ + if (!DeviceIoControl (p, PIPE_IOCTL_SET_PIPE_NAME, + (LPVOID) name, (wcslen (name) + 1) * sizeof (WCHAR), + NULL, 0, NULL, NULL)) + return FALSE; + return TRUE; +} + +extern "C" BOOL +GetPipeName (HANDLE p, WCHAR* name) +{ + DWORD actual; + if (!DeviceIoControl (p, PIPE_IOCTL_GET_PIPE_NAME, + NULL, 0, + (LPVOID)name, MAX_PATH * sizeof (WCHAR), + &actual, NULL)) + return FALSE; + return TRUE; +} + +extern "C" BOOL +CreatePipe (PHANDLE hReadPipe, + PHANDLE hWritePipe, + LPSECURITY_ATTRIBUTES lpPipeAttributes, + DWORD nSize) +{ + int inst; + WCHAR* wsKey; + HANDLE h; + + *hReadPipe = NULL; + *hWritePipe = NULL; + + for (inst = 0 ; inst < MAX_INSTANCES; inst++) + { + PrepareRegistryForInstance (inst, &wsKey); + h = ActivateDevice (wsKey, 0); + RegDeleteKey (HKEY_LOCAL_MACHINE, wsKey); + free (wsKey); + + /* Although MSDN documentcs that error should + return INVALID_HANDLE_VALUE, I see it returning + NULL here. */ + if (h != INVALID_HANDLE_VALUE && h != NULL) + break; + } + + if (inst == MAX_INSTANCES) + return FALSE; + + /* name + num + ':' + '0' */ + wchar_t device_name[(sizeof (NAME_BASE) - 1) + 2 + 1 + 1]; + wsprintf (device_name, L"%s%02d:", NAME_BASE, inst); + + *hReadPipe = CreateFile (device_name, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + SetPipeName (*hReadPipe, device_name); + + *hWritePipe = CreateFile (device_name, + GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + return TRUE; +} + +#if 0 + +struct PeekStruct +{ + DWORD Size; /* for future extension */ + PVOID lpBuffer, + DWORD nBufferSize, + + /* TODO: We need to use MapPtr for this to work */ + LPDWORD lpBytesRead, + LPDWORD lpTotalBytesAvail, + LPDWORD lpBytesLeftThisMessage + }; + +BOOL +PeekNamedPipe (HANDLE hNamedPipe, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesRead, + LPDWORD lpTotalBytesAvail, + LPDWORD lpBytesLeftThisMessage + ) +{ + DWORD avail; + DWORD actual; + + PeekStruct data; + data.Size = sizeof (PeekStruct); + data.lpBuffer = lpBuffer; + data.nBufferSize = nBufferSize; + data.lpBytesRead = lpBytesRead; + data.lpTotalBytesAvail = lpTotalBytesAvail; + data.lpBytesLeftThisMessage = lpBytesLeftThisMessage; + + if (!DeviceIoControl (hNamedPipe, PIPE_IOCTRL_PEEK_NAMED_PIPE, + NULL, 0, + (LPVOID)&data, sizeof (PeekStruct), &actual, NULL)) + return FALSE; + + /* We can detect here if we are talking to an older driver. */ + if (actual != data.Size) + return FALSE; + + return FALSE; +} + +#endif Copied: trunk/cegcc/tools/PipeLib/PipeLib.h (from rev 1011, trunk/cegcc/tools/PipeLib/PipeLib/PipeLib.h) =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib.h (rev 0) +++ trunk/cegcc/tools/PipeLib/PipeLib.h 2007-06-28 23:31:21 UTC (rev 1018) @@ -0,0 +1,46 @@ +/* Copyright (c) 2007, Pedro Alves + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#ifndef __PIPE_LIB_H__ +#define __PIPE_LIB_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +BOOL CreatePipe (PHANDLE,PHANDLE,LPSECURITY_ATTRIBUTES,DWORD); +BOOL GetPipeName (HANDLE, WCHAR*); + +/* Internal, for pipedev.dll debugging purposes. */ +BOOL SetPipeTag (HANDLE, const WCHAR*); + +#ifdef __cplusplus +} +#endif + + +#endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-28 23:34:34
|
Revision: 1019 http://svn.sourceforge.net/cegcc/?rev=1019&view=rev Author: pedroalves Date: 2007-06-28 16:34:32 -0700 (Thu, 28 Jun 2007) Log Message: ----------- * (PipeLib): Delete. * (PipeDev): Delete. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog Removed Paths: ------------- trunk/cegcc/tools/PipeLib/PipeDev/ trunk/cegcc/tools/PipeLib/PipeLib/ Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 23:31:21 UTC (rev 1018) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-28 23:34:32 UTC (rev 1019) @@ -1,5 +1,10 @@ 2007-06-29 Pedro Alves <ped...@po...> + * (PipeLib): Delete. + * (PipeDev): Delete. + +2007-06-29 Pedro Alves <ped...@po...> + * PipeLib/PipeLib.cpp : Move ... * PipeLib.cpp : ... here. Include PipeDev.h instead of PipeDevice.h. * PipeLib/PipeLib.h : Move ... This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-06-30 21:13:30
|
Revision: 1027 http://svn.sourceforge.net/cegcc/?rev=1027&view=rev Author: pedroalves Date: 2007-06-30 14:13:29 -0700 (Sat, 30 Jun 2007) Log Message: ----------- * Makefile (download): Depend on all instead of only on PipeDev.dll. * PipeLib.h (PIPELIB_API): New define. (CreatePipe, GetPipeName, SetPipeTag): Use PIPELIB_API. * PipeLib.cpp: Include windows.h earlier. (GetPipeName, SetPipeTag, PeekNamedPipe): Use PIPELIB_API. (CreatePipe): Use PIPELIB_API. Comment unused parameter names. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog trunk/cegcc/tools/PipeLib/Makefile trunk/cegcc/tools/PipeLib/PipeLib.cpp trunk/cegcc/tools/PipeLib/PipeLib.h Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-30 21:08:05 UTC (rev 1026) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-30 21:13:29 UTC (rev 1027) @@ -1,3 +1,14 @@ +2007-06-30 Pedro Alves <ped...@po...> + + * Makefile (download): Depend on all instead of only on + PipeDev.dll. + * PipeLib.h (PIPELIB_API): New define. + (CreatePipe, GetPipeName, SetPipeTag): Use PIPELIB_API. + * PipeLib.cpp: Include windows.h earlier. + (GetPipeName, SetPipeTag, PeekNamedPipe): Use + PIPELIB_API. + (CreatePipe): Use PIPELIB_API. Comment unused parameter names. + 2007-06-29 Pedro Alves <ped...@po...> * PipeLib: Delete. Modified: trunk/cegcc/tools/PipeLib/Makefile =================================================================== --- trunk/cegcc/tools/PipeLib/Makefile 2007-06-30 21:08:05 UTC (rev 1026) +++ trunk/cegcc/tools/PipeLib/Makefile 2007-06-30 21:13:29 UTC (rev 1027) @@ -25,7 +25,7 @@ rm -f $@ $(AR) r $@ $< -download: PipeDev.dll +download: all pcp PipeDev.dll ":/Windows/PipeDev.dll" clean-dev: Modified: trunk/cegcc/tools/PipeLib/PipeLib.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib.cpp 2007-06-30 21:08:05 UTC (rev 1026) +++ trunk/cegcc/tools/PipeLib/PipeLib.cpp 2007-06-30 21:13:29 UTC (rev 1027) @@ -24,9 +24,11 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <windows.h> + +#include "PipeLib.h" #include "PipeDev.h" -#include <windows.h> #include <devload.h> #include <stdlib.h> @@ -93,7 +95,7 @@ } /* Undocumented, for pipedev.dll debugging purposes only. */ -extern "C" BOOL +PIPELIB_API BOOL SetPipeTag (HANDLE p, const WCHAR* name) { if (!DeviceIoControl (p, PIPE_IOCTL_SET_PIPE_TAG, @@ -113,7 +115,7 @@ return TRUE; } -extern "C" BOOL +PIPELIB_API BOOL GetPipeName (HANDLE p, WCHAR* name) { DWORD actual; @@ -125,11 +127,11 @@ return TRUE; } -extern "C" BOOL +PIPELIB_API BOOL CreatePipe (PHANDLE hReadPipe, PHANDLE hWritePipe, - LPSECURITY_ATTRIBUTES lpPipeAttributes, - DWORD nSize) + LPSECURITY_ATTRIBUTES /* lpPipeAttributes */, + DWORD /* nSize */) { int inst; WCHAR* wsKey; @@ -145,9 +147,8 @@ RegDeleteKey (HKEY_LOCAL_MACHINE, wsKey); free (wsKey); - /* Although MSDN documentcs that error should - return INVALID_HANDLE_VALUE, I see it returning - NULL here. */ + /* Although MSDN documents the error as INVALID_HANDLE_VALUE, I + see it returning NULL here. */ if (h != INVALID_HANDLE_VALUE && h != NULL) break; } @@ -155,7 +156,7 @@ if (inst == MAX_INSTANCES) return FALSE; - /* name + num + ':' + '0' */ + /* name + num + ':' + '\0' */ wchar_t device_name[(sizeof (NAME_BASE) - 1) + 2 + 1 + 1]; wsprintf (device_name, L"%s%02d:", NAME_BASE, inst); @@ -194,7 +195,7 @@ LPDWORD lpBytesLeftThisMessage }; -BOOL +PIPELIB_API BOOL PeekNamedPipe (HANDLE hNamedPipe, LPVOID lpBuffer, DWORD nBufferSize, Modified: trunk/cegcc/tools/PipeLib/PipeLib.h =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib.h 2007-06-30 21:08:05 UTC (rev 1026) +++ trunk/cegcc/tools/PipeLib/PipeLib.h 2007-06-30 21:13:29 UTC (rev 1027) @@ -28,19 +28,16 @@ #define __PIPE_LIB_H__ #ifdef __cplusplus -extern "C" -{ +# define PIPELIB_API extern "C" +#else +# define PIPELIB_API #endif -BOOL CreatePipe (PHANDLE,PHANDLE,LPSECURITY_ATTRIBUTES,DWORD); -BOOL GetPipeName (HANDLE, WCHAR*); +PIPELIB_API BOOL CreatePipe (PHANDLE,PHANDLE,LPSECURITY_ATTRIBUTES,DWORD); +PIPELIB_API BOOL GetPipeName (HANDLE, WCHAR*); /* Internal, for pipedev.dll debugging purposes. */ -BOOL SetPipeTag (HANDLE, const WCHAR*); +PIPELIB_API BOOL SetPipeTag (HANDLE, const WCHAR*); -#ifdef __cplusplus -} -#endif - #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-07-01 01:53:45
|
Revision: 1033 http://svn.sourceforge.net/cegcc/?rev=1033&view=rev Author: pedroalves Date: 2007-06-30 18:47:48 -0700 (Sat, 30 Jun 2007) Log Message: ----------- Damn stupid bug. Writes should block until *all* the data is flushed. * PipeDev.cpp (Write): Remove breaknext and its usage. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog trunk/cegcc/tools/PipeLib/PipeDev.cpp Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-06-30 23:55:43 UTC (rev 1032) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-07-01 01:47:48 UTC (rev 1033) @@ -1,3 +1,7 @@ +2007-07-01 Pedro Alves <ped...@po...> + + * PipeDev.cpp (Write): Remove breaknext and its usage. + 2007-06-30 Pedro Alves <ped...@po...> * Makefile (download): Depend on all instead of only on Modified: trunk/cegcc/tools/PipeLib/PipeDev.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev.cpp 2007-06-30 23:55:43 UTC (rev 1032) +++ trunk/cegcc/tools/PipeLib/PipeDev.cpp 2007-07-01 01:47:48 UTC (rev 1033) @@ -180,7 +180,7 @@ { #ifndef NOLOCKS /* auto - only release one at a time. */ - EventHandle = CreateEvent (NULL, FALSE, FALSE, NULL); + EventHandle = CreateEvent (NULL, FALSE, FALSE, NULL); #endif } @@ -794,7 +794,6 @@ PipeDeviceContext* dev = pOpenContext->DeviceContext; - BOOL breaknext = FALSE; HANDLE Events[2]; do @@ -847,9 +846,6 @@ if (dwCount == 0) break; - - if (breaknext) - break; } LOG ("going to wait for event\n"); @@ -857,7 +853,6 @@ { case WAIT_OBJECT_0 + 1: LOG ("got read event\n"); - breaknext = TRUE; break; default: /* With either wait error or AbortEvent This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-07-02 01:20:57
|
Revision: 1036 http://svn.sourceforge.net/cegcc/?rev=1036&view=rev Author: pedroalves Date: 2007-07-01 18:20:56 -0700 (Sun, 01 Jul 2007) Log Message: ----------- * PipeLib.cpp (CreatePipe): Handle unexpected ActivateDevice failures. Record last error as ERROR_TOO_MANY_OPEN_FILES when there aren't any pipe slots left. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog trunk/cegcc/tools/PipeLib/PipeLib.cpp Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-07-02 00:54:55 UTC (rev 1035) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-07-02 01:20:56 UTC (rev 1036) @@ -1,3 +1,10 @@ +2007-07-02 Pedro Alves <ped...@po...> + Danny Backx <dan...@us...> + + * PipeLib.cpp (CreatePipe): Handle unexpected ActivateDevice + failures. Record last error as ERROR_TOO_MANY_OPEN_FILES when + there aren't any pipe slots left. + 2007-07-01 Pedro Alves <ped...@po...> * PipeDev.cpp (Write): Remove breaknext and its usage. Modified: trunk/cegcc/tools/PipeLib/PipeLib.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeLib.cpp 2007-07-02 00:54:55 UTC (rev 1035) +++ trunk/cegcc/tools/PipeLib/PipeLib.cpp 2007-07-02 01:20:56 UTC (rev 1036) @@ -147,6 +147,13 @@ RegDeleteKey (HKEY_LOCAL_MACHINE, wsKey); free (wsKey); + if (!h && GetLastError() != ERROR_DEVICE_IN_USE) + { + /* Something went wrong. Use GetLastError for extended + information. */ + return FALSE; + } + /* Although MSDN documents the error as INVALID_HANDLE_VALUE, I see it returning NULL here. */ if (h != INVALID_HANDLE_VALUE && h != NULL) @@ -154,7 +161,10 @@ } if (inst == MAX_INSTANCES) - return FALSE; + { + SetLastError (ERROR_TOO_MANY_OPEN_FILES); + return FALSE; + } /* name + num + ':' + '\0' */ wchar_t device_name[(sizeof (NAME_BASE) - 1) + 2 + 1 + 1]; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ped...@us...> - 2007-09-02 17:59:20
|
Revision: 1051 http://cegcc.svn.sourceforge.net/cegcc/?rev=1051&view=rev Author: pedroalves Date: 2007-09-02 10:59:12 -0700 (Sun, 02 Sep 2007) Log Message: ----------- Fix dumm bug. Writting to a pipe from a ro buffer, eg: write (pipe, "", 1) ... would fail, because of the reverse IsBadWritePtr/IsBadReadPtr usage. * PipeLib.cpp (Read): Switch to IsBadWritePtr. Only set last error to ERROR_BROKEN_PIPE if returning. (Write): Switch to IsBadReadPtr. Modified Paths: -------------- trunk/cegcc/tools/PipeLib/ChangeLog trunk/cegcc/tools/PipeLib/PipeDev.cpp Modified: trunk/cegcc/tools/PipeLib/ChangeLog =================================================================== --- trunk/cegcc/tools/PipeLib/ChangeLog 2007-09-02 17:55:11 UTC (rev 1050) +++ trunk/cegcc/tools/PipeLib/ChangeLog 2007-09-02 17:59:12 UTC (rev 1051) @@ -1,3 +1,9 @@ +2007-09-02 Pedro Alves <ped...@po...> + + * PipeLib.cpp (Read): Switch to IsBadWritePtr. Only set last + error to ERROR_BROKEN_PIPE if returning. + (Write): Switch to IsBadReadPtr. + 2007-07-02 Danny Backx <dan...@us...> Pedro Alves <ped...@po...> Modified: trunk/cegcc/tools/PipeLib/PipeDev.cpp =================================================================== --- trunk/cegcc/tools/PipeLib/PipeDev.cpp 2007-09-02 17:55:11 UTC (rev 1050) +++ trunk/cegcc/tools/PipeLib/PipeDev.cpp 2007-09-02 17:59:12 UTC (rev 1051) @@ -673,7 +673,7 @@ { LOGSCOPE ("\n"); - if (IsBadReadPtr (pBuffer, dwCount)) + if (IsBadWritePtr (pBuffer, dwCount)) { SetLastError (ERROR_INVALID_PARAMETER); LOG ("\n"); @@ -719,7 +719,6 @@ || dev->OpenCount == 0 /* or, ... weird */ ) { - SetLastError (ERROR_BROKEN_PIPE); if (needed - dwCount) { /* I don't know a way to report error and 'valid @@ -729,6 +728,7 @@ break; } LOG ("Pipe broken\n"); + SetLastError (ERROR_BROKEN_PIPE); return (DWORD) -1; } @@ -772,7 +772,7 @@ { LOGSCOPE ("\n"); - if (IsBadWritePtr ((void*) pBuffer, dwCount)) + if (IsBadReadPtr (pBuffer, dwCount)) { SetLastError (ERROR_INVALID_PARAMETER); LOG ("\n"); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |