- Timestamp:
- Jul 9, 2013 12:15:44 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/localipc.h
r47009 r47051 4 4 5 5 /* 6 * Copyright (C) 2006-201 0Oracle Corporation6 * Copyright (C) 2006-2013 Oracle Corporation 7 7 * 8 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 76 76 /** @name RTLocalIpcServerCreate flags 77 77 * @{ */ 78 /** The server can handle multiple session . */78 /** The server can handle multiple sessions. */ 79 79 #define RTLOCALIPC_FLAGS_MULTI_SESSION RT_BIT_32(0) 80 80 /** The mask of valid flags. */ … … 151 151 * @param pvBuffer Where to store the data. 152 152 * @param cbBuffer If pcbRead is non-NULL this indicates the maximum number of 153 * bytes to read. If pcbRead is NULL the this is the exact number153 * bytes to read. If pcbRead is NULL then this is the exact number 154 154 * of bytes to read. 155 155 * @param pcbRead Optional argument for indicating a partial read and returning -
trunk/src/VBox/Runtime/r3/win/localipc-win.cpp
r44529 r47051 5 5 6 6 /* 7 * Copyright (C) 2008-201 0Oracle Corporation7 * Copyright (C) 2008-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 42 42 #include <sddl.h> 43 43 44 #include <iprt/alloc.h> 45 #include <iprt/asm.h> 46 #include <iprt/assert.h> 47 #include <iprt/critsect.h> 48 #include <iprt/err.h> 49 #include <iprt/ldr.h> 44 50 #include <iprt/localipc.h> 51 #include <iprt/param.h> 52 #include <iprt/string.h> 45 53 #include <iprt/thread.h> 46 #include <iprt/critsect.h>47 #include <iprt/alloc.h>48 #include <iprt/assert.h>49 #include <iprt/param.h>50 #include <iprt/err.h>51 #include <iprt/string.h>52 #include <iprt/asm.h>53 54 54 55 #include "internal/magics.h" … … 139 140 { 140 141 /** The magic (RTLOCALIPCSESSION_MAGIC). */ 141 uint32_t u32Magic;142 uint32_t u32Magic; 142 143 /** Critical section protecting the structure. */ 143 RTCRITSECT CritSect;144 RTCRITSECT CritSect; 144 145 /** The number of references to the instance. 145 146 * @remarks The reference counting isn't race proof. */ 146 uint32_t volatile cRefs; 147 uint32_t volatile cRefs; 148 /** Set if there is already pending I/O. */ 149 bool fIOPending; 147 150 /** Indicates that there is a pending cancel request. */ 148 bool volatile fCancelled;151 bool volatile fCancelled; 149 152 /** The name pipe handle. */ 150 HANDLE hNmPipe;153 HANDLE hNmPipe; 151 154 /** The handle to the event object we're using for overlapped I/O. */ 152 HANDLE hEvent;155 HANDLE hEvent; 153 156 /** The overlapped I/O structure. */ 154 OVERLAPPED OverlappedIO; 157 OVERLAPPED OverlappedIO; 158 /** Bounce buffer for writes. */ 159 uint8_t *pbBounceBuf; 160 /** Amount of used buffer space. */ 161 size_t cbBounceBufUsed; 162 /** Amount of allocated buffer space. */ 163 size_t cbBounceBufAlloc; 155 164 } RTLOCALIPCSESSIONINT; 156 165 /** Pointer to a local IPC session instance (Windows). */ 157 166 typedef RTLOCALIPCSESSIONINT *PRTLOCALIPCSESSIONINT; 167 168 typedef BOOL WINAPI FNCONVERTSTRINGSECURITYDESCRIPTORTOSECURITYDESCRIPTOR(LPCTSTR, DWORD, PSECURITY_DESCRIPTOR, PULONG); 169 typedef FNCONVERTSTRINGSECURITYDESCRIPTORTOSECURITYDESCRIPTOR 170 *PFNCONVERTSTRINGSECURITYDESCRIPTORTOSECURITYDESCRIPTOR; /* No, nobody fell on the keyboard, really! */ 158 171 159 172 … … 169 182 * This is used by both RTLocalIpcServerCreate and RTLocalIpcServerListen. 170 183 * 171 * @returns Windows error code, that is NO_ERROR and *phNmPipe on success and some ERROR_* on failure. 172 * 184 * @return IPRT status code. 173 185 * @param phNmPipe Where to store the named pipe handle on success. This 174 186 * will be set to INVALID_HANDLE_VALUE on failure. … … 177 189 * Governs the FILE_FLAG_FIRST_PIPE_INSTANCE flag. 178 190 */ 179 static DWORDrtLocalIpcServerWinCreatePipeInstance(PHANDLE phNmPipe, const char *pszFullPipeName, bool fFirst)191 static int rtLocalIpcServerWinCreatePipeInstance(PHANDLE phNmPipe, const char *pszFullPipeName, bool fFirst) 180 192 { 181 193 *phNmPipe = INVALID_HANDLE_VALUE; 182 194 183 /* 184 * We'll create a security descriptor from a SDDL that denies 185 * access to network clients (this is local IPC after all), it 186 * makes some further restrictions to prevent non-authenticated 187 * users from screwing around. 188 */ 189 DWORD err; 195 /** @todo Stuff this into RTInitOnce. Later. */ 196 PFNCONVERTSTRINGSECURITYDESCRIPTORTOSECURITYDESCRIPTOR 197 pfnConvertStringSecurityDescriptorToSecurityDescriptor = NULL; 198 199 RTLDRMOD hAdvApi32 = NIL_RTLDRMOD; 200 int rc = RTLdrLoadSystem("Advapi32.lib", true /*fNoUnload*/, &hAdvApi32); 201 if (RT_SUCCESS(rc)) 202 rc = RTLdrGetSymbol(hAdvApi32, "ConvertStringSecurityDescriptorToSecurityDescriptor", 203 (void**)&pfnConvertStringSecurityDescriptorToSecurityDescriptor); 204 190 205 PSECURITY_DESCRIPTOR pSecDesc = NULL; 191 #if 0 /** @todo dynamically resolve this as it is the only thing that prevents 192 * loading IPRT on NT4. */ 193 if (ConvertStringSecurityDescriptorToSecurityDescriptor(RTLOCALIPC_WIN_SDDL, 194 SDDL_REVISION_1, 195 &pSecDesc, 196 NULL)) 197 #else 198 AssertFatalFailed(); 199 SetLastError(-1); 200 if (0) 201 #endif 206 if (RT_SUCCESS(rc)) 207 { 208 AssertPtr(pfnConvertStringSecurityDescriptorToSecurityDescriptor); 209 210 /* 211 * We'll create a security descriptor from a SDDL that denies 212 * access to network clients (this is local IPC after all), it 213 * makes some further restrictions to prevent non-authenticated 214 * users from screwing around. 215 */ 216 if (!pfnConvertStringSecurityDescriptorToSecurityDescriptor(RTLOCALIPC_WIN_SDDL, 217 SDDL_REVISION_1, 218 &pSecDesc, 219 NULL)) 220 { 221 rc = RTErrConvertFromWin32(GetLastError()); 222 } 223 } 224 else 225 { 226 /* Windows OSes < W2K SP2 not supported for now, bail out. */ 227 /** @todo Implement me! */ 228 rc = VERR_NOT_SUPPORTED; 229 } 230 231 if (hAdvApi32 != NIL_RTLDRMOD) 232 RTLdrClose(hAdvApi32); 233 234 if (RT_SUCCESS(rc)) 202 235 { 203 236 SECURITY_ATTRIBUTES SecAttrs; … … 209 242 | PIPE_WAIT 210 243 | FILE_FLAG_OVERLAPPED; 211 if (fFirst) 212 fOpenMode |= FILE_FLAG_FIRST_PIPE_INSTANCE; /* Note! Requires W2K SP2+. */ 244 245 bool fSupportsFirstInstance = false; 246 247 OSVERSIONINFOEX OSInfoEx; 248 RT_ZERO(OSInfoEx); 249 OSInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); 250 if ( GetVersionEx((LPOSVERSIONINFO) &OSInfoEx) 251 && OSInfoEx.dwPlatformId == VER_PLATFORM_WIN32_NT) 252 { 253 if ( /* Vista+. */ 254 OSInfoEx.dwMajorVersion >= 6 255 /* Windows XP+. */ 256 || ( OSInfoEx.dwMajorVersion == 5 257 && OSInfoEx.dwMinorVersion > 0) 258 /* Windows 2000. */ 259 || ( OSInfoEx.dwMajorVersion == 5 260 && OSInfoEx.dwMinorVersion == 0 261 && OSInfoEx.wServicePackMajor >= 2)) 262 { 263 /* Requires at least W2K (5.0) SP2+. This is non-fatal. */ 264 fSupportsFirstInstance = true; 265 } 266 } 267 268 if (fFirst && fSupportsFirstInstance) 269 fOpenMode |= FILE_FLAG_FIRST_PIPE_INSTANCE; 213 270 214 271 HANDLE hNmPipe = CreateNamedPipe(pszFullPipeName, /* lpName */ … … 220 277 30*1000, /* nDefaultTimeOut = 30 sec */ 221 278 &SecAttrs); /* lpSecurityAttributes */ 222 err = GetLastError(); 279 223 280 LocalFree(pSecDesc); 224 281 if (hNmPipe != INVALID_HANDLE_VALUE) 225 282 { 226 283 *phNmPipe = hNmPipe; 227 return NO_ERROR; 228 } 229 } 230 else 231 err = GetLastError(); 232 233 AssertReturn(err != NO_ERROR, ERROR_GEN_FAILURE); 234 return err; 284 } 285 else 286 rc = RTErrConvertFromWin32(GetLastError()); 287 } 288 289 return rc; 235 290 } 236 291 … … 264 319 if (RT_SUCCESS(rc)) 265 320 { 266 DWORD err = NO_ERROR;267 pThis->hEvent = CreateEvent(NULL /*lpEventAttributes*/, TRUE /*bManualReset*/,FALSE /*bInitialState*/, NULL /*lpName*/);321 pThis->hEvent = CreateEvent(NULL /*lpEventAttributes*/, TRUE /*bManualReset*/, 322 FALSE /*bInitialState*/, NULL /*lpName*/); 268 323 if (pThis->hEvent != NULL) 269 324 { 270 memset(&pThis->OverlappedIO, 0, sizeof(pThis->OverlappedIO));325 RT_ZERO(pThis->OverlappedIO); 271 326 pThis->OverlappedIO.Internal = STATUS_PENDING; 272 327 pThis->OverlappedIO.hEvent = pThis->hEvent; 273 328 274 err = rtLocalIpcServerWinCreatePipeInstance(&pThis->hNmPipe, pThis->szName, true /* fFirst */); 275 if (err == NO_ERROR) 329 rc = rtLocalIpcServerWinCreatePipeInstance(&pThis->hNmPipe, 330 pThis->szName, true /* fFirst */); 331 if (RT_SUCCESS(rc)) 276 332 { 277 333 *phServer = pThis; 278 334 return VINF_SUCCESS; 279 335 } 336 337 BOOL fRc = CloseHandle(pThis->hEvent); 338 AssertMsg(fRc, ("%d\n", GetLastError())); NOREF(fRc); 280 339 } 281 340 else 282 err = GetLastError(); 283 rc = RTErrConvertFromWin32(err); 341 rc = RTErrConvertFromWin32(GetLastError()); 342 343 int rc2 = RTCritSectDelete(&pThis->CritSect); 344 AssertRC(rc2); 284 345 } 285 346 RTMemFree(pThis); … … 372 433 /* 373 434 * Try connect a client. We need to use overlapped I/O here because 374 * of the cancellation aby RTLocalIpcServerCancel and RTLocalIpcServerDestroy.435 * of the cancellation done by RTLocalIpcServerCancel and RTLocalIpcServerDestroy. 375 436 */ 376 437 SetLastError(NO_ERROR); … … 387 448 388 449 RTCritSectEnter(&pThis->CritSect); 389 if ( !pThis->fCancelled 450 if ( !pThis->fCancelled /* Event signalled but not cancelled? */ 390 451 && pThis->u32Magic == RTLOCALIPCSERVER_MAGIC) 391 452 { … … 397 458 * will be assigned to the client session. 398 459 */ 399 if ( 400 || 460 if ( fRc 461 || err == ERROR_PIPE_CONNECTED) 401 462 { 402 463 HANDLE hNmPipe; … … 488 549 static int rtLocalIpcWinCreateSession(PRTLOCALIPCSESSION phClientSession, HANDLE hNmPipeSession) 489 550 { 551 AssertPtrReturn(phClientSession, VERR_INVALID_POINTER); 552 AssertReturn(hNmPipeSession != INVALID_HANDLE_VALUE, VERR_INVALID_PARAMETER); 553 490 554 int rc; 491 555 … … 504 568 if (RT_SUCCESS(rc)) 505 569 { 506 pThis->hEvent = CreateEvent(NULL /*lpEventAttributes*/, TRUE /*bManualReset*/, FALSE /*bInitialState*/, NULL /*lpName*/); 570 pThis->hEvent = CreateEvent(NULL /*lpEventAttributes*/, TRUE /*bManualReset*/, 571 FALSE /*bInitialState*/, NULL /*lpName*/); 507 572 if (pThis->hEvent != NULL) 508 573 { 509 memset(&pThis->OverlappedIO, 0, sizeof(pThis->OverlappedIO));574 RT_ZERO(pThis->OverlappedIO); 510 575 pThis->OverlappedIO.Internal = STATUS_PENDING; 511 576 pThis->OverlappedIO.hEvent = pThis->hEvent; … … 529 594 } 530 595 531 532 596 RTDECL(int) RTLocalIpcSessionConnect(PRTLOCALIPCSESSION phSession, const char *pszName, uint32_t fFlags) 533 597 { 534 return VINF_SUCCESS; 598 AssertPtrReturn(phSession, VERR_INVALID_POINTER); 599 AssertPtrReturn(pszName, VERR_INVALID_POINTER); 600 AssertReturn(!fFlags, VERR_INVALID_PARAMETER); /* Flags currently unused, must be 0. */ 601 602 PRTLOCALIPCSESSIONINT pThis = (PRTLOCALIPCSESSIONINT)RTMemAlloc(sizeof(*pThis)); 603 if (!pThis) 604 return VERR_NO_MEMORY; 605 606 pThis->u32Magic = RTLOCALIPCSESSION_MAGIC; 607 pThis->cRefs = 1; /* The one we return. */ 608 pThis->fIOPending = false; 609 pThis->fCancelled = false; 610 pThis->pbBounceBuf = NULL; 611 pThis->cbBounceBufAlloc = 0; 612 pThis->cbBounceBufUsed = 0; 613 614 int rc = RTCritSectInit(&pThis->CritSect); 615 if (RT_SUCCESS(rc)) 616 { 617 pThis->hEvent = CreateEvent(NULL /*lpEventAttributes*/, TRUE /*bManualReset*/, 618 FALSE /*bInitialState*/, NULL /*lpName*/); 619 if (pThis->hEvent != NULL) 620 { 621 RT_ZERO(pThis->OverlappedIO); 622 pThis->OverlappedIO.Internal = STATUS_PENDING; 623 pThis->OverlappedIO.hEvent = pThis->hEvent; 624 625 char *pszPipe; 626 if (RTStrAPrintf(&pszPipe, "%s%s", RTLOCALIPC_WIN_PREFIX, pszName)) 627 { 628 HANDLE hPipe = CreateFile(pszPipe, /* pipe name */ 629 GENERIC_READ | /* read and write access */ 630 GENERIC_WRITE, 631 0, /* no sharing */ 632 NULL, /* default security attributes */ 633 OPEN_EXISTING, /* opens existing pipe */ 634 FILE_FLAG_OVERLAPPED, /* default attributes */ 635 NULL); /* no template file */ 636 RTStrFree(pszPipe); 637 if (hPipe != INVALID_HANDLE_VALUE) 638 { 639 pThis->hNmPipe = hPipe; 640 return VINF_SUCCESS; 641 } 642 else 643 rc = RTErrConvertFromWin32(GetLastError()); 644 } 645 else 646 rc = VERR_NO_MEMORY; 647 648 BOOL fRc = CloseHandle(pThis->hEvent); 649 AssertMsg(fRc, ("%d\n", GetLastError())); NOREF(fRc); 650 } 651 else 652 rc = RTErrConvertFromWin32(GetLastError()); 653 654 int rc2 = RTCritSectDelete(&pThis->CritSect); 655 AssertRC(rc2); 656 } 657 658 RTMemFree(pThis); 659 return rc; 535 660 } 536 661 … … 594 719 RTDECL(int) RTLocalIpcSessionRead(RTLOCALIPCSESSION hSession, void *pvBuffer, size_t cbBuffer, size_t *pcbRead) 595 720 { 721 PRTLOCALIPCSESSIONINT pThis = hSession; 722 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 723 AssertReturn(pThis->u32Magic == RTLOCALIPCSESSION_MAGIC, VERR_INVALID_HANDLE); 724 AssertPtrReturn(pvBuffer, VERR_INVALID_POINTER); 725 /* pcbRead is optional. */ 726 727 int rc = RTCritSectEnter(&pThis->CritSect); 728 if (RT_SUCCESS(rc)) 729 { 730 /* No concurrent readers, sorry. */ 731 if (pThis->cRefs == 0) 732 { 733 pThis->cRefs++; 734 735 /* 736 * If pcbRead is non-NULL this indicates the maximum number of bytes to read. 737 * If pcbRead is NULL the this is the exact number of bytes to read. 738 */ 739 size_t cbToRead = pcbRead ? *pcbRead : cbBuffer; 740 size_t cbTotalRead = 0; 741 while (cbToRead > 0) 742 { 743 /* 744 * Kick of a an overlapped read. It should return immediately if 745 * there is bytes in the buffer. If not, we'll cancel it and see 746 * what we get back. 747 */ 748 rc = ResetEvent(pThis->OverlappedIO.hEvent); Assert(rc == TRUE); 749 DWORD cbRead = 0; 750 pThis->fIOPending = true; 751 RTCritSectLeave(&pThis->CritSect); 752 753 if (ReadFile(pThis->hNmPipe, pvBuffer, 754 cbToRead <= ~(DWORD)0 ? (DWORD)cbToRead : ~(DWORD)0, 755 &cbRead, &pThis->OverlappedIO)) 756 rc = VINF_SUCCESS; 757 else if (GetLastError() == ERROR_IO_PENDING) 758 { 759 WaitForSingleObject(pThis->OverlappedIO.hEvent, INFINITE); 760 if (GetOverlappedResult(pThis->hNmPipe, &pThis->OverlappedIO, 761 &cbRead, TRUE /*fWait*/)) 762 rc = VINF_SUCCESS; 763 else 764 rc = RTErrConvertFromWin32(GetLastError()); 765 } 766 else 767 rc = RTErrConvertFromWin32(GetLastError()); 768 769 RTCritSectEnter(&pThis->CritSect); 770 pThis->fIOPending = false; 771 if (RT_FAILURE(rc)) 772 break; 773 774 /* Advance. */ 775 cbToRead -= cbRead; 776 cbTotalRead += cbRead; 777 pvBuffer = (uint8_t *)pvBuffer + cbRead; 778 } 779 780 if (pcbRead) 781 { 782 *pcbRead = cbTotalRead; 783 if ( RT_FAILURE(rc) 784 && cbTotalRead 785 && rc != VERR_INVALID_POINTER) 786 rc = VINF_SUCCESS; 787 } 788 789 pThis->cRefs--; 790 } 791 else 792 rc = VERR_WRONG_ORDER; 793 RTCritSectLeave(&pThis->CritSect); 794 } 795 796 return rc; 797 } 798 799 800 /** 801 * Common worker for handling I/O completion. 802 * 803 * This is used by RTLocalIpcSessionClose and RTLocalIpcSessionWrite. 804 * 805 * @returns IPRT status code. 806 * @param pThis The pipe instance handle. 807 */ 808 static int rtLocalIpcSessionWriteCheckCompletion(PRTLOCALIPCSESSIONINT pThis) 809 { 810 int rc; 811 DWORD dwRc = WaitForSingleObject(pThis->OverlappedIO.hEvent, 0); 812 if (dwRc == WAIT_OBJECT_0) 813 { 814 DWORD cbWritten = 0; 815 if (GetOverlappedResult(pThis->hNmPipe, &pThis->OverlappedIO, &cbWritten, TRUE)) 816 { 817 for (;;) 818 { 819 if (cbWritten >= pThis->cbBounceBufUsed) 820 { 821 pThis->fIOPending = false; 822 rc = VINF_SUCCESS; 823 break; 824 } 825 826 /* resubmit the remainder of the buffer - can this actually happen? */ 827 memmove(&pThis->pbBounceBuf[0], &pThis->pbBounceBuf[cbWritten], pThis->cbBounceBufUsed - cbWritten); 828 rc = ResetEvent(pThis->OverlappedIO.hEvent); Assert(rc == TRUE); 829 if (!WriteFile(pThis->hNmPipe, pThis->pbBounceBuf, (DWORD)pThis->cbBounceBufUsed, 830 &cbWritten, &pThis->OverlappedIO)) 831 { 832 if (GetLastError() == ERROR_IO_PENDING) 833 rc = VINF_TRY_AGAIN; 834 else 835 { 836 pThis->fIOPending = false; 837 if (GetLastError() == ERROR_NO_DATA) 838 rc = VERR_BROKEN_PIPE; 839 else 840 rc = RTErrConvertFromWin32(GetLastError()); 841 } 842 break; 843 } 844 Assert(cbWritten > 0); 845 } 846 } 847 else 848 { 849 pThis->fIOPending = false; 850 rc = RTErrConvertFromWin32(GetLastError()); 851 } 852 } 853 else if (dwRc == WAIT_TIMEOUT) 854 rc = VINF_TRY_AGAIN; 855 else 856 { 857 pThis->fIOPending = false; 858 if (dwRc == WAIT_ABANDONED) 859 rc = VERR_INVALID_HANDLE; 860 else 861 rc = RTErrConvertFromWin32(GetLastError()); 862 } 863 return rc; 864 } 865 866 867 RTDECL(int) RTLocalIpcSessionWrite(RTLOCALIPCSESSION hSession, const void *pvBuffer, size_t cbBuffer) 868 { 869 PRTLOCALIPCSESSIONINT pThis = hSession; 870 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 871 AssertReturn(pThis->u32Magic == RTLOCALIPCSESSION_MAGIC, VERR_INVALID_HANDLE); 872 AssertPtrReturn(pvBuffer, VERR_INVALID_POINTER); 873 AssertReturn(cbBuffer, VERR_INVALID_PARAMETER); 874 875 int rc = RTCritSectEnter(&pThis->CritSect); 876 if (RT_SUCCESS(rc)) 877 { 878 /* No concurrent writers, sorry. */ 879 if (pThis->cRefs == 0) 880 { 881 pThis->cRefs++; 882 883 /* 884 * If I/O is pending, wait for it to complete. 885 */ 886 if (pThis->fIOPending) 887 { 888 rc = rtLocalIpcSessionWriteCheckCompletion(pThis); 889 while (rc == VINF_TRY_AGAIN) 890 { 891 Assert(pThis->fIOPending); 892 HANDLE hEvent = pThis->OverlappedIO.hEvent; 893 RTCritSectLeave(&pThis->CritSect); 894 WaitForSingleObject(pThis->OverlappedIO.hEvent, INFINITE); 895 RTCritSectEnter(&pThis->CritSect); 896 } 897 } 898 if (RT_SUCCESS(rc)) 899 { 900 Assert(!pThis->fIOPending); 901 902 /* 903 * Try write everything. 904 * No bounce buffering, cUsers protects us. 905 */ 906 size_t cbTotalWritten = 0; 907 while (cbBuffer > 0) 908 { 909 rc = ResetEvent(pThis->OverlappedIO.hEvent); Assert(rc == TRUE); 910 pThis->fIOPending = true; 911 RTCritSectLeave(&pThis->CritSect); 912 913 DWORD cbWritten = 0; 914 if (WriteFile(pThis->hNmPipe, pvBuffer, 915 cbBuffer <= ~(DWORD)0 ? (DWORD)cbBuffer : ~(DWORD)0, 916 &cbWritten, &pThis->OverlappedIO)) 917 rc = VINF_SUCCESS; 918 else if (GetLastError() == ERROR_IO_PENDING) 919 { 920 WaitForSingleObject(pThis->OverlappedIO.hEvent, INFINITE); 921 if (GetOverlappedResult(pThis->hNmPipe, &pThis->OverlappedIO, &cbWritten, TRUE /*fWait*/)) 922 rc = VINF_SUCCESS; 923 else 924 rc = RTErrConvertFromWin32(GetLastError()); 925 } 926 else if (GetLastError() == ERROR_NO_DATA) 927 rc = VERR_BROKEN_PIPE; 928 else 929 rc = RTErrConvertFromWin32(GetLastError()); 930 931 RTCritSectEnter(&pThis->CritSect); 932 pThis->fIOPending = false; 933 if (RT_FAILURE(rc)) 934 break; 935 936 /* Advance. */ 937 pvBuffer = (char const *)pvBuffer + cbWritten; 938 cbTotalWritten += cbWritten; 939 cbBuffer -= cbWritten; 940 } 941 } 942 943 pThis->cRefs--; 944 } 945 else 946 rc = VERR_WRONG_ORDER; 947 RTCritSectLeave(&pThis->CritSect); 948 } 949 950 return rc; 951 } 952 953 954 RTDECL(int) RTLocalIpcSessionFlush(RTLOCALIPCSESSION hSession) 955 { 956 /* No flushing on Windows needed since RTLocalIpcSessionWrite will block until 957 * all data was written (or an error occurred). */ 958 /** @todo Implement this as soon as we want an explicit asynchronous version of 959 * RTLocalIpcSessionWrite on Windows. */ 596 960 return VINF_SUCCESS; 597 961 } 598 962 599 963 600 RTDECL(int) RTLocalIpcSessionWrite(RTLOCALIPCSESSION hSession, const void *pvBuffer, size_t cbBuffer) 964 RTDECL(int) RTLocalIpcSessionWaitForData(RTLOCALIPCSESSION hSession, uint32_t cMillies) 965 { 966 PRTLOCALIPCSESSIONINT pThis = hSession; 967 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 968 AssertReturn(pThis->u32Magic == RTLOCALIPCSESSION_MAGIC, VERR_INVALID_HANDLE); 969 970 int rc = RTCritSectEnter(&pThis->CritSect); 971 if (RT_SUCCESS(rc)) 972 { 973 /* No concurrent waiters, sorry. */ 974 if (pThis->cRefs == 0) 975 { 976 pThis->cRefs++; 977 RTCritSectLeave(&pThis->CritSect); 978 979 DWORD dwTimeout = cMillies == RT_INDEFINITE_WAIT 980 ? INFINITE : cMillies; 981 DWORD dwRc = WaitForSingleObject(pThis->OverlappedIO.hEvent, dwTimeout); 982 983 RTCritSectEnter(&pThis->CritSect); 984 if (dwRc == WAIT_TIMEOUT) 985 { 986 rc = VERR_TIMEOUT; 987 } 988 else if (dwRc == WAIT_ABANDONED) 989 { 990 rc = VERR_BROKEN_PIPE; 991 } 992 else if (dwRc == WAIT_FAILED) 993 rc = RTErrConvertFromWin32(GetLastError()); 994 995 pThis->cRefs--; 996 } 997 else 998 rc = VERR_WRONG_ORDER; 999 RTCritSectLeave(&pThis->CritSect); 1000 } 1001 1002 return rc; 1003 } 1004 1005 1006 RTDECL(int) RTLocalIpcSessionCancel(RTLOCALIPCSESSION hSession) 601 1007 { 602 1008 return VINF_SUCCESS; … … 604 1010 605 1011 606 RTDECL(int) RTLocalIpcSessionFlush(RTLOCALIPCSESSION hSession)607 {608 return VINF_SUCCESS;609 }610 611 612 RTDECL(int) RTLocalIpcSessionWaitForData(RTLOCALIPCSESSION hSession, uint32_t cMillies)613 {614 RTThreadSleep(1000);615 return VINF_SUCCESS;616 }617 618 619 RTDECL(int) RTLocalIpcSessionCancel(RTLOCALIPCSESSION hSession)620 {621 return VINF_SUCCESS;622 }623 624 625 1012 RTDECL(int) RTLocalIpcSessionQueryProcess(RTLOCALIPCSESSION hSession, PRTPROCESS pProcess) 626 1013 {
Note:
See TracChangeset
for help on using the changeset viewer.