diff --git a/microstack/ILibParsers.c b/microstack/ILibParsers.c index 0fa1a6f..6937b3f 100644 --- a/microstack/ILibParsers.c +++ b/microstack/ILibParsers.c @@ -2819,6 +2819,33 @@ void ILibChain_AddWaitHandle(void *chain, HANDLE h, int msTIMEOUT, ILibChain_Wai ILibForceUnBlockChain(chain); } +void __stdcall ILibChain_RemoveWaitHandle_APC(ULONG_PTR u) +{ + ILibBaseChain *chain = (ILibBaseChain*)((void**)u)[0]; + HANDLE h = (HANDLE)((void**)u)[1]; + + void *node = ILibLinkedList_GetNode_Search(chain->auxSelectHandles, NULL, h); + if (node != NULL) + { + // + // We found the HANDLE, so if we remove the HANDLE from the list, and + // set the unblock flag, we'll be good to go + // + ILibLinkedList_Remove(node); + chain->UnblockFlag = 1; + } +} +void ILibChain_RemoveWaitHandle(void *chain, HANDLE h) +{ + // + // We must dispatch an APC to remove the wait handle, + // because we can't change the wait list during a WaitForMultipleObjectsEx() call + // + void **tmp = (void**)ILibMemory_SmartAllocate(2 * sizeof(void*)); + tmp[0] = chain; + tmp[1] = h; + QueueUserAPC((PAPCFUNC)ILibChain_RemoveWaitHandle_APC, ILibChain_GetMicrostackThreadHandle(chain), (ULONG_PTR)tmp); +} #endif /*! \fn ILibStartChain(void *Chain) diff --git a/microstack/ILibParsers.h b/microstack/ILibParsers.h index f589f58..f8da004 100644 --- a/microstack/ILibParsers.h +++ b/microstack/ILibParsers.h @@ -974,6 +974,7 @@ int ILibIsRunningOnChainThread(void* chain); char *ILibChain_GetMetaDataFromDescriptorSet(void *chain, fd_set *inr, fd_set *inw, fd_set *ine); #ifdef WIN32 void ILibChain_AddWaitHandle(void *chain, HANDLE h, int msTIMEOUT, ILibChain_WaitHandleHandler handler, void *user); + void ILibChain_RemoveWaitHandle(void *chain, HANDLE h); #define tv2LTtv1(ptv1, ptv2) ((ptv2)->tv_sec < (ptv1)->tv_sec || ((ptv2)->tv_sec == (ptv1)->tv_sec && (ptv2)->tv_usec < (ptv1)->tv_usec)) #define tv2LTEtv1(ptv1, ptv2) (tv2LTtv1(ptv2,ptv1) || ((ptv2)->tv_sec == (ptv1)->tv_sec && (ptv2)->tv_usec <= (ptv1)->tv_usec)) #define tvnonzero(ptv) ((ptv)->tv_sec != 0 || (ptv)->tv_usec != 0) diff --git a/microstack/ILibProcessPipe.c b/microstack/ILibProcessPipe.c index 07126c4..fccc055 100644 --- a/microstack/ILibProcessPipe.c +++ b/microstack/ILibProcessPipe.c @@ -1868,6 +1868,34 @@ int ILibProcessPipe_Pipe_ReadEx(ILibProcessPipe_Pipe targetPipe, char *buffer, i return(0); } } +BOOL ILibProcessPipe_Pipe_WriteEx_sink(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus status, void* user) +{ + ILibProcessPipe_PipeObject *j = (ILibProcessPipe_PipeObject*)user; + DWORD bytesWritten; + + if (GetOverlappedResult(j->mPipe_WriteEnd, j->mwOverlapped, &bytesWritten, FALSE)) + { + if (j->user4 != NULL) + { + ((ILibProcessPipe_Pipe_WriteExHandler)j->user4)(j, j->user3, bytesWritten > 0 ? 0 : 1, (int)bytesWritten); + } + } + else + { + if (GetLastError() == ERROR_IO_PENDING) + { + return(TRUE); + } + else + { + if (j->user4 != NULL) + { + ((ILibProcessPipe_Pipe_WriteExHandler)j->user4)(j, j->user3, 1, 0); + } + } + } + return(FALSE); +} int ILibProcessPipe_Pipe_WriteEx(ILibProcessPipe_Pipe targetPipe, char *buffer, int bufferLength, void *user, ILibProcessPipe_Pipe_WriteExHandler OnWriteHandler) { ILibProcessPipe_PipeObject *j = (ILibProcessPipe_PipeObject*)targetPipe; @@ -1875,18 +1903,48 @@ int ILibProcessPipe_Pipe_WriteEx(ILibProcessPipe_Pipe targetPipe, char *buffer, { void **extra; j->mwOverlapped = (OVERLAPPED*)ILibMemory_Allocate(sizeof(OVERLAPPED), sizeof(void*), NULL, (void**)&extra); + if ((j->mwOverlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) { ILIBCRITICALEXIT(254); } extra[0] = j; } j->user3 = user; j->user4 = OnWriteHandler; - if (!WriteFileEx(j->mPipe_WriteEnd, buffer, bufferLength, j->mwOverlapped, ILibProcessPipe_Pipe_Write_CompletionRoutine)) + + if (!WriteFile(j->mPipe_WriteEnd, buffer, bufferLength, NULL, j->mwOverlapped)) { - return(GetLastError()); + if (GetLastError() == ERROR_IO_PENDING) + { + ILibChain_AddWaitHandle(j->manager->ChainLink.ParentChain, j->mwOverlapped->hEvent, -1, ILibProcessPipe_Pipe_WriteEx_sink, j); + return(0); + } + // Error + if (OnWriteHandler != NULL) { OnWriteHandler(j, user, 1, 0); } + return(1); } else { + // Write completed + if (OnWriteHandler != NULL) { OnWriteHandler(j, user, 0, bufferLength); } return(0); } + + +// ILibProcessPipe_PipeObject *j = (ILibProcessPipe_PipeObject*)targetPipe; +// if (j->mwOverlapped == NULL) +// { +// void **extra; +// j->mwOverlapped = (OVERLAPPED*)ILibMemory_Allocate(sizeof(OVERLAPPED), sizeof(void*), NULL, (void**)&extra); +// extra[0] = j; +//} +// j->user3 = user; +// j->user4 = OnWriteHandler; +// if (!WriteFileEx(j->mPipe_WriteEnd, buffer, bufferLength, j->mwOverlapped, ILibProcessPipe_Pipe_Write_CompletionRoutine)) +// { +// return(GetLastError()); +// } +// else +// { +// return(0); +// } } DWORD ILibProcessPipe_Process_GetPID(ILibProcessPipe_Process p) { return(p != NULL ? (DWORD)((ILibProcessPipe_Process_Object*)p)->PID : 0); } #else