ReactOS.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
January
2004
December
November
October
September
August
July
June
May
April
March
February
List overview
Download
Ros-diffs
August 2016
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
ros-diffs@reactos.org
20 participants
462 discussions
Start a n
N
ew thread
[pschweitzer] 72108: [MPR] Check for the right capability. Already sent upstream. CORE-11757
by pschweitzer@svn.reactos.org
Author: pschweitzer Date: Thu Aug 4 12:27:59 2016 New Revision: 72108 URL:
http://svn.reactos.org/svn/reactos?rev=72108&view=rev
Log: [MPR] Check for the right capability. Already sent upstream. CORE-11757 Modified: trunk/reactos/dll/win32/mpr/wnet.c Modified: trunk/reactos/dll/win32/mpr/wnet.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/mpr/wnet.c?rev=7…
============================================================================== --- trunk/reactos/dll/win32/mpr/wnet.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/mpr/wnet.c [iso-8859-1] Thu Aug 4 12:27:59 2016 @@ -2110,7 +2110,7 @@ for (index = 0; index < providerTable->numProviders; index++) { if(providerTable->table[index].getCaps(WNNC_CONNECTION) & - WNNC_CON_GETCONNECTIONS) + WNNC_CON_CANCELCONNECTION) { if (providerTable->table[index].cancelConnection) ret = providerTable->table[index].cancelConnection((LPWSTR)lpName, fForce);
8 years, 4 months
1
0
0
0
[pschweitzer] 72107: [MPR] Add a missing break
by pschweitzer@svn.reactos.org
Author: pschweitzer Date: Thu Aug 4 12:25:51 2016 New Revision: 72107 URL:
http://svn.reactos.org/svn/reactos?rev=72107&view=rev
Log: [MPR] Add a missing break Modified: trunk/reactos/dll/win32/mpr/wnet.c Modified: trunk/reactos/dll/win32/mpr/wnet.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/mpr/wnet.c?rev=7…
============================================================================== --- trunk/reactos/dll/win32/mpr/wnet.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/mpr/wnet.c [iso-8859-1] Thu Aug 4 12:25:51 2016 @@ -1454,6 +1454,7 @@ } HeapFree(GetProcessHeap(), 0, handles); ret = WN_SUCCESS; + break; case WNET_ENUMERATOR_TYPE_NULL: ret = WN_SUCCESS; break;
8 years, 4 months
1
0
0
0
[zhu] 72106: Mostly fully working TCP. Occasional crash due to faulty mbox implementation in sys_arch.c.
by zhu@svn.reactos.org
Author: zhu Date: Wed Aug 3 22:00:57 2016 New Revision: 72106 URL:
http://svn.reactos.org/svn/reactos?rev=72106&view=rev
Log: Mostly fully working TCP. Occasional crash due to faulty mbox implementation in sys_arch.c. Modified: branches/GSoC_2016/lwIP-tcpip/base/applications/network/tcpclient/main.c branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/tcp.c branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/lwip/tcp.h Modified: branches/GSoC_2016/lwIP-tcpip/base/applications/network/tcpclient/main.c URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/base/appli…
============================================================================== --- branches/GSoC_2016/lwIP-tcpip/base/applications/network/tcpclient/main.c [iso-8859-1] (original) +++ branches/GSoC_2016/lwIP-tcpip/base/applications/network/tcpclient/main.c [iso-8859-1] Wed Aug 3 22:00:57 2016 @@ -3,7 +3,7 @@ #include <winsock2.h> #define LENGTH 255 -#define NUM_CLIENTS 1 +#define NUM_CLIENTS 32 DWORD WINAPI ClientThreadMain(LPVOID lpParam) { SOCKET Sock; Modified: branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/drivers/ne…
============================================================================== --- branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c [iso-8859-1] (original) +++ branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c [iso-8859-1] Wed Aug 3 22:00:57 2016 @@ -16,9 +16,9 @@ volatile long int GlContextCount; volatile long int PcbCount; -PADDRESS_FILE AddrFileArray[16]; -PTCP_CONTEXT ContextArray[16]; -struct tcp_pcb *PCBArray[16]; +PADDRESS_FILE AddrFileArray[128]; +PTCP_CONTEXT ContextArray[128]; +struct tcp_pcb *PCBArray[128]; KSPIN_LOCK AddrFileArrayLock; KSPIN_LOCK ContextArrayLock; @@ -237,7 +237,7 @@ * ADDRESS_FILE. This mutex guards against concurrent access from multiple execution contexts if and * only if the Context is associated with an Address File. If TcpIpAssociateAddress has been called * on a TCP_CONTEXT struct, this mutex should be held when reading from or writing to any and all - * fields in the struct until TcpIpDisassociateAddress is call on the same struct. + * fields in the struct until TcpIpDisassociateAddress is called on the same struct. * * Mutex acquisition returns TRUE if the mutex has been acquired. Returns FALSE if the mutex could * not be acquired due to the Context having no association to any Address File. @@ -374,10 +374,10 @@ { NTSTATUS Status; - /* Check that the IRP was not already cancelled */ + /* Check that the IRP was not already canceled */ if (Irp->Cancel) { - DPRINT("IRP already cancelled\n"); + DPRINT("IRP already canceled\n"); Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; return STATUS_CANCELLED; @@ -495,7 +495,7 @@ } goto COMPLETE_IRP; case TCP_REQUEST_CANCEL_MODE_PRESERVE : - /* For requests that do not deallocate the PCB when cancelled, determine and clear the + /* For requests that do not deallocate the PCB when canceled, determine and clear the * appropriate TCP State bit */ switch (Request->PendingMode) { @@ -549,7 +549,15 @@ PTCP_CONTEXT Context; PTCP_REQUEST Request; + /* Check that the IRP isn't already being canceled */ + if (Irp->Cancel == TRUE) + { + IoReleaseCancelSpinLock(Irp->CancelIrql); + return; + } + /* Block potential repeated cancellations */ + Irp->Cancel = TRUE; IoSetCancelRoutine(Irp, NULL); /* This function is always called with the Cancel lock held */ @@ -2085,6 +2093,7 @@ /* Block potential cancellations */ Irp = Request->Payload.PendingIrp; + Irp->Cancel = TRUE; IoSetCancelRoutine(Irp, NULL); /* Dequeue Request and increment list walk */ @@ -2199,6 +2208,7 @@ Irp = Request->Payload.PendingIrp; /* Block cancellations */ + Irp->Cancel = TRUE; IoSetCancelRoutine(Irp, NULL); /* One last sanity check */ @@ -2448,6 +2458,7 @@ /* Found a matching request. Block cancellations, dequeue, * and break out of the list walk. */ Irp = Request->Payload.PendingIrp; + Irp->Cancel = TRUE; IoSetCancelRoutine(Irp, NULL); RemoveEntryList(&Request->ListEntry); goto FOUND; @@ -2563,6 +2574,7 @@ { /* Immediately block any cancellations */ Irp = Request->Payload.PendingIrp; + Irp->Cancel = TRUE; IoSetCancelRoutine(Irp, NULL); /* Dequeue the entry and jump to handler */ Modified: branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/drivers/ne…
============================================================================== --- branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h [iso-8859-1] (original) +++ branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h [iso-8859-1] Wed Aug 3 22:00:57 2016 @@ -31,7 +31,7 @@ //#define TCPIP_NDEBUG #ifndef TCPIP_NDEBUG KSPIN_LOCK IRPArrayLock; -PIRP IRPArray[16]; +PIRP IRPArray[256]; volatile long int IRPCount; #define ADD_IRP(Irp) \ @@ -81,7 +81,7 @@ KeReleaseSpinLockFromDpcLevel(&IRPArrayLock) KSPIN_LOCK IRPSPArrayLock; -PIO_STACK_LOCATION IRPSPArray[16]; +PIO_STACK_LOCATION IRPSPArray[256]; volatile long int IRPSPCount; #define ADD_IRPSP(IrpSp) \ @@ -255,4 +255,4 @@ AddressSetTtl( _In_ TDIEntityID ID, _In_ PVOID InBuffer, - _In_ ULONG BufferSize); + _In_ ULONG BufferSize); Modified: branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/tcp.c URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/drivers/ne…
============================================================================== --- branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/tcp.c [iso-8859-1] (original) +++ branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/tcp.c [iso-8859-1] Wed Aug 3 22:00:57 2016 @@ -59,6 +59,7 @@ else *PortNumber = Bit; PortNumberHint = *PortNumber; + KeReleaseSpinLock(&PortBitmapSpinlock, OldIrql); return FALSE; } Modified: branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/lwip/tcp.h URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/sdk/lib/dr…
============================================================================== --- branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/lwip/tcp.h [iso-8859-1] (original) +++ branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/lwip/tcp.h [iso-8859-1] Wed Aug 3 22:00:57 2016 @@ -373,7 +373,12 @@ * Serializes all kernel network activity to circumvent lwIP core's lack of thread-safety. */ KMUTEX MTSerialMutex; - +#define ACQUIRE_SERIAL_MUTEX() \ + KeWaitForMutexObject(&MTSerialMutex, Executive, KernelMode, FALSE, NULL) + +#define RELEASE_SERIAL_MUTEX() \ + KeReleaseMutex(&MTSerialMutex, FALSE) +/* #define ACQUIRE_SERIAL_MUTEX() \ DPRINT("Acquiring MTSerialMutex on thread %p\n", PsGetCurrentThreadId()); \ KeWaitForMutexObject(&MTSerialMutex, Executive, KernelMode, FALSE, NULL); \ @@ -383,7 +388,7 @@ DPRINT("Releasing MTSerialMutex on thread %p\n", PsGetCurrentThreadId()); \ KeReleaseMutex(&MTSerialMutex, FALSE); \ DPRINT("MTSerialMutex released on thread %p\n", PsGetCurrentThreadId()) - +*/ const char* tcp_debug_state_str(enum tcp_state s); #ifdef __cplusplus
8 years, 4 months
1
0
0
0
[hbelusca] 72105: [SHELL32]: Fix copypasta bug.
by hbelusca@svn.reactos.org
Author: hbelusca Date: Wed Aug 3 20:02:28 2016 New Revision: 72105 URL:
http://svn.reactos.org/svn/reactos?rev=72105&view=rev
Log: [SHELL32]: Fix copypasta bug. Modified: trunk/reactos/dll/win32/shell32/shelldesktop/CDesktopBrowser.cpp Modified: trunk/reactos/dll/win32/shell32/shelldesktop/CDesktopBrowser.cpp URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/shelldes…
============================================================================== --- trunk/reactos/dll/win32/shell32/shelldesktop/CDesktopBrowser.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/shelldesktop/CDesktopBrowser.cpp [iso-8859-1] Wed Aug 3 20:02:28 2016 @@ -119,7 +119,7 @@ /* Calculate the size and pos of the window */ RECT rect; - if (!GetSystemMetrics(SM_CXVIRTUALSCREEN) || GetSystemMetrics(SM_CYVIRTUALSCREEN)) + if (!GetSystemMetrics(SM_CXVIRTUALSCREEN) || !GetSystemMetrics(SM_CYVIRTUALSCREEN)) { SetRect(&rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); }
8 years, 4 months
1
0
0
0
[zhu] 72104: Added global KMUTEX serializing all threads that access lwIP. Added global arrays to debug IRPs. Implemented TDI_LISTEN handler. Made the Context mutex recursive within a thread. Modif...
by zhu@svn.reactos.org
Author: zhu Date: Wed Aug 3 19:57:20 2016 New Revision: 72104 URL:
http://svn.reactos.org/svn/reactos?rev=72104&view=rev
Log: Added global KMUTEX serializing all threads that access lwIP. Added global arrays to debug IRPs. Implemented TDI_LISTEN handler. Made the Context mutex recursive within a thread. Modified the way listening connection contexts are handled. Now creates a new TCP_CONTEXT struct on a TDI_LISTEN, which dies on the TDI_LISTEN's cancellation. Minor modifications to make some functions work better with the large changes. Removed the majority of debug printout statements. Modified: branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/interface.c branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/main.c branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/arch/sys_arch.h branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/lwip/tcp.h branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/lwip/tcpip.h branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/sys_arch.c Modified: branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/drivers/ne…
============================================================================== --- branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c [iso-8859-1] (original) +++ branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c [iso-8859-1] Wed Aug 3 19:57:20 2016 @@ -13,7 +13,7 @@ #ifndef NDEBUG /* Debug global variables, for convenience */ volatile long int AddrFileCount; -volatile long int ContextCount; +volatile long int GlContextCount; volatile long int PcbCount; PADDRESS_FILE AddrFileArray[16]; @@ -23,6 +23,20 @@ KSPIN_LOCK AddrFileArrayLock; KSPIN_LOCK ContextArrayLock; KSPIN_LOCK PCBArrayLock; + +#define _KeAcquireSpinLock(Lock,Irql) \ + if (KeGetCurrentIrql() != 0) \ + { \ + DPRINT("\n Acquiring %p %s at IRQL %u\n", Lock, #Lock, KeGetCurrentIrql()); \ + }; \ + KeAcquireSpinLock(Lock, Irql) + +#define _KeReleaseSpinLock(Lock,Irql) \ + if (KeGetCurrentIrql() != 2) \ + { \ + DPRINT("\n Releasing %p %s at IRQL %u\n", Lock, #Lock, KeGetCurrentIrql()); \ + }; \ + KeReleaseSpinLock(Lock, Irql) #define ADD_ADDR_FILE(AddrFile) \ DPRINT("Adding Address File %p\n", AddrFile); \ @@ -77,21 +91,21 @@ #define ADD_CONTEXT(Context) \ DPRINT("Adding Context %p\n", Context); \ KeAcquireSpinLock(&ContextArrayLock, &OldIrql); \ - ContextArray[ContextCount] = Context; \ - ContextCount++; \ + ContextArray[GlContextCount] = Context; \ + GlContextCount++; \ KeReleaseSpinLock(&ContextArrayLock, OldIrql) #define ADD_CONTEXT_DPC(Context) \ DPRINT("Adding Context %p\n", Context); \ KeAcquireSpinLockAtDpcLevel(&ContextArrayLock); \ - ContextArray[ContextCount] = Context; \ - ContextCount++; \ + ContextArray[GlContextCount] = Context; \ + GlContextCount++; \ KeReleaseSpinLockFromDpcLevel(&ContextArrayLock) #define REMOVE_CONTEXT(Context) \ DPRINT("Removing Context %p\n", Context); \ KeAcquireSpinLock(&ContextArrayLock, &OldIrql); \ - for (i = 0; i < ContextCount; i++) \ + for (i = 0; i < GlContextCount; i++) \ { \ if (Context == ContextArray[i]) \ { \ @@ -103,13 +117,13 @@ ContextArray[i+1] = NULL; \ } \ } \ - ContextCount--; \ + GlContextCount--; \ KeReleaseSpinLock(&ContextArrayLock, OldIrql) #define REMOVE_CONTEXT_DPC(Context) \ DPRINT("Removing Context %p\n", Context); \ KeAcquireSpinLockAtDpcLevel(&ContextArrayLock); \ - for (i = 0; i < ContextCount; i++) \ + for (i = 0; i < GlContextCount; i++) \ { \ if (Context == ContextArray[i]) \ { \ @@ -121,7 +135,7 @@ ContextArray[i+1] = NULL; \ } \ } \ - ContextCount--; \ + GlContextCount--; \ KeReleaseSpinLockFromDpcLevel(&ContextArrayLock) #define ADD_PCB(pcb) \ @@ -202,6 +216,10 @@ static err_t lwip_tcp_receive_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err); static err_t lwip_tcp_sent_callback(void *arg, struct tcp_pcb *tpcb, u16_t len); +/* Forward-declare helper function */ +VOID CloseAddress(PADDRESS_FILE AddressFile); +NTSTATUS DisassociateAddress(PTCP_CONTEXT Context); + #define AddrIsUnspecified(Address) ((Address->in_addr == 0) || (Address->in_addr == 0xFFFFFFFF)) #define TCP_SET_STATE(State,Context) \ @@ -214,6 +232,21 @@ DPRINT("Removing State %s from Context %p\n", #State, Context); \ Context->TcpState &= ~State +/** + * Recursive mutex guarding a TCP_CONTEXT using a KSPIN_LOCK residing in the Context's associated + * ADDRESS_FILE. This mutex guards against concurrent access from multiple execution contexts if and + * only if the Context is associated with an Address File. If TcpIpAssociateAddress has been called + * on a TCP_CONTEXT struct, this mutex should be held when reading from or writing to any and all + * fields in the struct until TcpIpDisassociateAddress is call on the same struct. + * + * Mutex acquisition returns TRUE if the mutex has been acquired. Returns FALSE if the mutex could + * not be acquired due to the Context having no association to any Address File. + * + * A disassociated context should be inherently safe from concurrent access because the only + * remaining reference to it should reside in an lwIP Protocol Control Block as the callback + * argument. Thus, lwIP callback functions can safely ignore the return value while all other + * functions should treat a return value of FALSE as a non-recoverable error. + **/ VOID InitializeContextMutex( PTCP_CONTEXT Context @@ -230,9 +263,14 @@ { HANDLE Thread; KIRQL OldIrql; - + PADDRESS_FILE AddressFile; PKSPIN_LOCK Lock; + +#ifndef NDEBUG + Thread = PsGetCurrentThreadId(); + DPRINT("Thread %p acquiring lock on Context %p\n", Thread, Context); +#endif AddressFile = Context->AddressFile; if (AddressFile == NULL) @@ -242,9 +280,9 @@ return FALSE; } Lock = &AddressFile->AssociatedContextsLock; - + Thread = PsGetCurrentThreadId(); - + AGAIN: /* Start mutex acquisition */ KeAcquireSpinLock(Lock, &OldIrql); @@ -261,12 +299,12 @@ KeReleaseSpinLock(Lock, OldIrql); goto AGAIN; } - + /* We passed all tests, we have exclusive access to this Context. */ Context->MutexOwner = Thread; KeReleaseSpinLock(Lock, OldIrql); InterlockedIncrement(&Context->MutexDepth); - + return TRUE; } @@ -275,9 +313,22 @@ PTCP_CONTEXT Context ) { - if (InterlockedDecrement(&Context->MutexDepth) == 0) - { - Context->MutexOwner = NULL; + HANDLE Thread; + + Thread = PsGetCurrentThreadId(); + DPRINT("Thread %p releasing lock on Context %p\n", Thread, Context); + + /* If the releasing call came from the mutex owner, do release. Otherwise, do nothing. */ + if (Context->MutexOwner == Thread) + { + if (InterlockedDecrement(&Context->MutexDepth) == 0) + { + Context->MutexOwner = NULL; + } + } + else + { + DPRINT1("Release mutex from non-owner\n"); } } @@ -297,17 +348,17 @@ Request = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Request), TAG_TCP_REQUEST); if (Request == NULL) { - DPRINT("Not enough resources\n"); + DPRINT1("Not enough resources\n"); return STATUS_NO_MEMORY; } Request->Payload.PendingIrp = Payload; Request->CancelMode = CancelMode; Request->PendingMode = PendingMode; Request->PayloadType = PayloadType; - + /* Enqueue request into Context's request list */ InsertTailList(&Context->RequestListHead, &Request->ListEntry); - + return STATUS_PENDING; } @@ -315,16 +366,14 @@ NTSTATUS PrepareIrpForCancel( PIRP Irp, + PTCP_CONTEXT Context, PDRIVER_CANCEL CancelRoutine, UCHAR CancelMode, UCHAR PendingMode ) { NTSTATUS Status; - - PIO_STACK_LOCATION IrpSp; - PTCP_CONTEXT Context; - + /* Check that the IRP was not already cancelled */ if (Irp->Cancel) { @@ -333,17 +382,13 @@ Irp->IoStatus.Information = 0; return STATUS_CANCELLED; } - - /* Get TCP Context */ - IrpSp = IoGetCurrentIrpStackLocation(Irp); - Context = IrpSp->FileObject->FsContext; - + /* Create and enqueue TCP Request */ Status = EnqueueRequest(Irp, Context, CancelMode, PendingMode, TCP_REQUEST_PAYLOAD_IRP); - + /* Set the IRP's Cancel routine */ IoSetCancelRoutine(Irp, CancelRoutine); - + return Status; } @@ -361,17 +406,20 @@ #ifndef NDEBUG KIRQL OldIrql; INT i; -#endif + PIO_STACK_LOCATION IrpSp; +#endif + LONG ContextCount; + PIRP Irp; PTCP_CONTEXT AcceptingContext; - + /* If this was just a request completion, skip lwIP PCB cleanup and go straight to IRP * completion */ if (Status == STATUS_SUCCESS) { goto COMPLETE_IRP; } - + /* This is not a simple completion. Perform cleanup depending on Request payload type. */ switch (Request->PayloadType) { @@ -379,29 +427,40 @@ /* The Request holds a pending IRP */ goto CLEANUP_PCB; case TCP_REQUEST_PAYLOAD_CONTEXT : - /* The Request holds a dummy Context meant incomming newly accepted connections */ + /* The Request holds a dummy Context meant for incomming newly accepted connections */ AcceptingContext = Request->Payload.Context; - + /* If an incomming connection has already been accepted, terminate it. */ if (Request->PendingMode == TCP_REQUEST_PENDING_ACCEPTED_CONNECTION) { #ifndef NDEBUG REMOVE_PCB(AcceptingContext->lwip_tcp_pcb); #endif + ACQUIRE_SERIAL_MUTEX(); tcp_close(AcceptingContext->lwip_tcp_pcb); + RELEASE_SERIAL_MUTEX(); } - - /* If we created the Context without a TDI_CREATE, deallocate it. */ - if (AcceptingContext->CreatedWithoutRequest == TRUE) + + /* If the Context does not have an upper-level reference, deallocate it. */ + if (AcceptingContext->ReferencedByUpperLayer == FALSE) { - InterlockedDecrement(&AcceptingContext->AddressFile->ContextCount); + /* If removing this Context removes the last reference to its Address File, also + * deallocate the Address File. */ + ContextCount = InterlockedDecrement(&AcceptingContext->AddressFile->ContextCount); + if (ContextCount < 1) + { + CloseAddress(AcceptingContext->AddressFile); + } +#ifndef NDEBUG + REMOVE_CONTEXT(AcceptingContext); +#endif ExFreePoolWithTag(AcceptingContext, TAG_TCP_CONTEXT); } - + /* Skip IRP completion, because there is no IRP to complete. */ goto FINISH; default : - DPRINT("We should never reach here. Something is wrong.\n"); + DPRINT1("We should never reach here. Something is wrong.\n"); goto FINISH; } @@ -416,10 +475,12 @@ #ifndef NDEBUG REMOVE_PCB(Context->lwip_tcp_pcb); #endif + ACQUIRE_SERIAL_MUTEX(); tcp_close(Context->lwip_tcp_pcb); + RELEASE_SERIAL_MUTEX(); Context->lwip_tcp_pcb = NULL; } - break; + goto COMPLETE_IRP; case TCP_REQUEST_CANCEL_MODE_ABORT : TCP_SET_STATE(TCP_STATE_ABORTED, Context); if (Context->lwip_tcp_pcb != NULL) @@ -427,10 +488,12 @@ #ifndef NDEBUG REMOVE_PCB(Context->lwip_tcp_pcb); #endif + ACQUIRE_SERIAL_MUTEX(); tcp_abort(Context->lwip_tcp_pcb); + RELEASE_SERIAL_MUTEX(); Context->lwip_tcp_pcb = NULL; } - break; + goto COMPLETE_IRP; case TCP_REQUEST_CANCEL_MODE_PRESERVE : /* For requests that do not deallocate the PCB when cancelled, determine and clear the * appropriate TCP State bit */ @@ -443,21 +506,26 @@ TCP_RMV_STATE(TCP_STATE_RECEIVING, Context); break; default : - DPRINT("We should never reach here. Something is wrong.\n"); + DPRINT1("We should never reach here. Something is wrong.\n"); goto FINISH; } - break; + goto COMPLETE_IRP; default : - DPRINT("We should never reach here. Something is wrong.\n"); + DPRINT1("We should never reach here. Something is wrong.\n"); goto FINISH; } - + COMPLETE_IRP: /* Complete the IRP */ Irp = Request->Payload.PendingIrp; Irp->IoStatus.Status = Status; +#ifndef NDEBUG + IrpSp = IoGetCurrentIrpStackLocation(Irp); + REMOVE_IRP(Irp); + REMOVE_IRPSP(IrpSp); +#endif IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); - + FINISH: /* Deallocate the TCP Request */ ExFreePoolWithTag(Request, TAG_TCP_REQUEST); @@ -470,18 +538,23 @@ _Inout_ _IRQL_uses_cancel_ struct _IRP *Irp ) { +#ifndef NDEBUG + INT i; + KIRQL OldIrql; +#endif + PIO_STACK_LOCATION IrpSp; PLIST_ENTRY Entry; PLIST_ENTRY Head; PTCP_CONTEXT Context; PTCP_REQUEST Request; - + /* Block potential repeated cancellations */ IoSetCancelRoutine(Irp, NULL); - + /* This function is always called with the Cancel lock held */ IoReleaseCancelSpinLock(Irp->CancelIrql); - + /* The file types distinguishes between some protocols */ IrpSp = IoGetCurrentIrpStackLocation(Irp); switch ((ULONG)IrpSp->FileObject->FsContext2) @@ -491,46 +564,79 @@ case TDI_CONNECTION_FILE : goto TCP_CANCEL; default : - DPRINT("IRP does not contain a valid FileObject\n"); + DPRINT1("IRP does not contain a valid FileObject\n"); goto FINISH; } - + DGRAM_CANCEL: - DPRINT("Datagram cancel not yet implemented\n"); + DPRINT1("Datagram cancel not yet implemented\n"); goto FINISH; - + TCP_CANCEL: Context = IrpSp->FileObject->FsContext; GetExclusiveContextAccess(Context); + /* If this is a cancellation on a TDI_LISTEN request, we need to disassociate and close the + * Context. AFD does not know about the extra Context we keep for listening sockets. AFD only + * cares about actual connection endpoints. */ + if (IrpSp->MinorFunction == TDI_LISTEN) + { + /* Disassociate the listening Context, which we grab from the AddressFile. */ + Context = Context->AddressFile->Listener; + DisassociateAddress(Context); + + /* If the lwIP PCB still exists, close it. Since we are deallocating the PCB's associated + * Context, we also need to clear the Context pointer in the PCB. */ + if (Context->lwip_tcp_pcb) + { +#ifndef NDEBUG + REMOVE_PCB(Context->lwip_tcp_pcb); +#endif + ACQUIRE_SERIAL_MUTEX(); + tcp_arg(Context->lwip_tcp_pcb, NULL); + tcp_close(Context->lwip_tcp_pcb); + RELEASE_SERIAL_MUTEX(); + } + + /* Deallocate the Context. The corresponding Address File's ContextCount should have been + * decremented when the Context was disassociated. */ +#ifndef NDEBUG + REMOVE_CONTEXT(Context); +#endif + ExFreePoolWithTag(Context, TAG_TCP_CONTEXT); + + return; + } + /* Walk the TCP Context's list of requests to find one with this IRP */ Head = &Context->RequestListHead; Entry = Head->Flink; while (Entry != Head) { Request = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry); - - /* Finding a matching request and entering this IF statement releases the list lock and - * returns */ + if (Request->Payload.PendingIrp == Irp) { /* Immediately remove the request from the queue before processing */ - DPRINT("Dequeueing Pending Request from %p\n", Context); RemoveEntryList(&Request->ListEntry); Irp->IoStatus.Information = 0; CleanupRequest(Request, STATUS_CANCELLED, Context); ReleaseExclusiveContextAccess(Context); return; } - + Entry = Entry->Flink; } - + ReleaseExclusiveContextAccess(Context); - - DPRINT("Did not find a matching TCP Request, we may leave a dead IRP pointer somewhere\n"); + + DPRINT1("Did not find a matching TCP Request, we may leave a dead IRP pointer somewhere\n"); FINISH: +#ifndef NDEBUG + REMOVE_IRP(Irp); + REMOVE_IRPSP(IrpSp); +#endif IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); return; } @@ -543,7 +649,7 @@ #ifndef NDEBUG AddrFileCount = 0; - ContextCount = 0; + GlContextCount = 0; PcbCount = 0; KeInitializeSpinLock(&AddrFileArrayLock); @@ -564,7 +670,7 @@ { PADDRESS_FILE AddressFile; PLIST_ENTRY Entry; - + /* If a netif is specified, check for AddressFile with matching netif and port in order to * detect duplicates */ if (lwip_netif != NULL) @@ -600,7 +706,7 @@ AddressFile = ExAllocatePoolWithTag(NonPagedPool, sizeof(*AddressFile), TAG_ADDRESS_FILE); if (AddressFile == NULL) { - DPRINT("Not enough resources\n"); + DPRINT1("Not enough resources\n"); return STATUS_NO_MEMORY; } #ifndef NDEBUG @@ -632,7 +738,7 @@ /* TCP variables */ AddressFile->HasListener = FALSE; KeInitializeSpinLock(&AddressFile->AssociatedContextsLock); - + /* UDP and RAW variables */ KeInitializeSpinLock(&AddressFile->RequestLock); InitializeListHead(&AddressFile->RequestListHead); @@ -644,7 +750,7 @@ FINISH: /* Output the Address File */ *_AddressFile = AddressFile; - + return STATUS_SUCCESS; } @@ -662,8 +768,6 @@ struct netif *lwip_netif; ip_addr_t IpAddr; - - DPRINT("TcpIpcreateAddress(PIRP %p, PTDI_ADDRESS %p, IPPROTO %d)\n", Irp, Address, Protocol); /* For a specified address, find a matching netif and, if needed, a free port. For unspecified * addresses, the lwip_netif is set to NULL. */ @@ -684,14 +788,16 @@ Status = STATUS_INVALID_ADDRESS; goto FAIL; } - + /* If port is unspecified, grab a free port from lwIP */ if (Address->sin_port == 0) { switch (Protocol) { case IPPROTO_TCP : + ACQUIRE_SERIAL_MUTEX(); Address->sin_port = (USHORT)tcp_new_port(); + RELEASE_SERIAL_MUTEX(); break; case IPPROTO_UDP : Address->sin_port = (USHORT)udp_new_port(); @@ -741,7 +847,7 @@ IrpSp->FileObject->FsContext = AddressFile; IrpSp->FileObject->FsContext2 = (PVOID)TDI_TRANSPORT_ADDRESS_FILE; } - + return Status; } @@ -754,13 +860,13 @@ INT i; #endif KIRQL OldIrql; - + /* Remove the Address File from global lists before further processing */ KeAcquireSpinLock(&AddressListLock, &OldIrql); RemoveEntryList(&AddressFile->ListEntry); KeReleaseSpinLock(&AddressListLock, OldIrql); RemoveEntityInstance(&AddressFile->Instance); - + /* For ICMP, RAW, UDP addresses, we need to deallocate the lwIP PCB */ switch (AddressFile->Protocol) { @@ -776,11 +882,11 @@ goto NO_REQUESTS; default : /* We should never reach here */ - DPRINT("Closing Address File with unknown protocol, %d. This should never happen.\n", + DPRINT1("Closing Address File with unknown protocol, %d. This should never happen.\n", AddressFile->Protocol); break; } - + /* Finish pending requests for RAW and UDP addresses */ NO_REQUESTS: @@ -796,8 +902,6 @@ _In_ PADDRESS_FILE AddressFile ) { - DPRINT("TcpIpCloseAddress(PADDRESS_FILE %p)\n", AddressFile); - /* Check if there are still references to this Address File */ if (InterlockedDecrement(&AddressFile->RefCount) > 0) { @@ -813,7 +917,7 @@ } CloseAddress(AddressFile); - + return STATUS_SUCCESS; } @@ -829,13 +933,11 @@ #endif PIO_STACK_LOCATION IrpSp; PTCP_CONTEXT Context; - - DPRINT("TcpIpCreateContext(PIRP %p, PTDI_ADDRESS_IP %p, IPPROTO %d)\n", Irp, Address, Protocol); /* Do not support anything other than TCP right now */ if (Protocol != IPPROTO_TCP) { - DPRINT("Creating connection context for non-TCP protocol: %d\n", Protocol); + DPRINT1("Creating connection context for non-TCP protocol: %d\n", Protocol); return STATUS_INVALID_PARAMETER; } @@ -843,7 +945,7 @@ Context = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Context), TAG_TCP_CONTEXT); if (Context == NULL) { - DPRINT("Not enough resources\n"); + DPRINT1("Not enough resources\n"); return STATUS_NO_MEMORY; } #ifndef NDEBUG @@ -854,9 +956,9 @@ TCP_SET_STATE(TCP_STATE_CREATED, Context); Context->AddressFile = NULL; InitializeListHead(&Context->RequestListHead); - Context->CreatedWithoutRequest = FALSE; + Context->ReferencedByUpperLayer = TRUE; InitializeContextMutex(Context); - + /* We defer PCB creation until TcpIpAssociateAddress(), since this Context could be a dummy * connection endpoint used to poll/wait for new accepted connections */ Context->lwip_tcp_pcb = NULL; @@ -879,15 +981,13 @@ KIRQL OldIrql; #endif - DPRINT("TcpIpCloseContext(PTCP_CONTEXT %p)\n", Context); - /* Sanity check */ if (Context->AddressFile != NULL) { - DPRINT("Context retains address association\n"); + DPRINT1("Context retains address association\n"); return STATUS_INVALID_PARAMETER; } - + /* If the lwIP PCB still exists, close it. Since we are deallocating the PCB's associated * Context, we also need to clear the Context pointer in the PCB. */ if (Context->lwip_tcp_pcb) @@ -895,17 +995,19 @@ #ifndef NDEBUG REMOVE_PCB(Context->lwip_tcp_pcb); #endif + ACQUIRE_SERIAL_MUTEX(); tcp_arg(Context->lwip_tcp_pcb, NULL); tcp_close(Context->lwip_tcp_pcb); - } - + RELEASE_SERIAL_MUTEX(); + } + /* Deallocate the Context. The corresponding Address File's ContextCount should have been * decremented when the Context was disassociated. */ #ifndef NDEBUG REMOVE_CONTEXT(Context); #endif ExFreePoolWithTag(Context, TAG_TCP_CONTEXT); - + return STATUS_SUCCESS; } @@ -916,16 +1018,14 @@ { KIRQL OldIrql; NTSTATUS Status; - + PADDRESS_FILE AddressFile; PFILE_OBJECT FileObject; PIO_STACK_LOCATION IrpSp; PTCP_CONTEXT Context; PTDI_REQUEST_KERNEL_ASSOCIATE RequestInfo; - + err_t lwip_err; - - DPRINT("TcpIpAssociateAddress(PIRP %p)\n", Irp); IrpSp = IoGetCurrentIrpStackLocation(Irp); @@ -940,12 +1040,12 @@ NULL); if (Status != STATUS_SUCCESS) { - DPRINT("Failed to dereference FileObject: 0x%08x\n", Status); + DPRINT1("Failed to dereference FileObject: 0x%08x\n", Status); return Status; } if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) { - DPRINT("File object should be an Address File\n"); + DPRINT1("File object should be an Address File\n"); ObDereferenceObject(FileObject); return STATUS_INVALID_PARAMETER; } @@ -954,7 +1054,7 @@ /* Get the TCP Context we are associating */ if (IrpSp->FileObject->FsContext2 != (PVOID)TDI_CONNECTION_FILE) { - DPRINT("File object should be a TCP Context\n"); + DPRINT1("File object should be a TCP Context\n"); ObDereferenceObject(FileObject); return STATUS_INVALID_PARAMETER; } @@ -963,11 +1063,11 @@ /* Sanity checks */ if ((AddressFile->Protocol != IPPROTO_TCP) || (Context->TcpState != TCP_STATE_CREATED)) { - DPRINT("We should be associating a new TCP Context with a TCP Address File\n"); + DPRINT1("We should be associating a new TCP Context with a TCP Address File\n"); ObDereferenceObject(FileObject); return STATUS_INVALID_PARAMETER; } - + /* If there is already a listener listening on the address, then this is a dummy connection * endpoint used to poll/wait for new accepted connections. In this case, we skip creating and * binding a new PCB. */ @@ -975,15 +1075,16 @@ { goto NO_PCB; } - + /* Create a new lwIP PCB and initialize callback data */ Context->lwip_tcp_pcb = tcp_new(); #ifndef NDEBUG ADD_PCB(Context->lwip_tcp_pcb); #endif + ACQUIRE_SERIAL_MUTEX(); tcp_arg(Context->lwip_tcp_pcb, Context); tcp_err(Context->lwip_tcp_pcb, lwip_tcp_err_callback); - + /* Attempt to bind the PCB. lwIP internally handles INADDR_ANY. */ lwip_err = tcp_bind( Context->lwip_tcp_pcb, @@ -997,70 +1098,63 @@ } case (ERR_BUF) : { - DPRINT("lwIP ERR_BUFF\n"); + RELEASE_SERIAL_MUTEX(); + DPRINT1("lwIP ERR_BUFF\n"); Status = STATUS_NO_MEMORY; goto FINISH; } case (ERR_VAL) : { - DPRINT("lwIP ERR_VAL\n"); + RELEASE_SERIAL_MUTEX(); + DPRINT1("lwIP ERR_VAL\n"); Status = STATUS_INVALID_PARAMETER; goto FINISH; } case (ERR_USE) : { - DPRINT("lwIP ERR_USE\n"); + RELEASE_SERIAL_MUTEX(); + DPRINT1("lwIP ERR_USE\n"); Status = STATUS_ADDRESS_ALREADY_EXISTS; goto FINISH; } default : { - DPRINT("lwIP unexpected error\n"); + RELEASE_SERIAL_MUTEX(); + DPRINT1("lwIP unexpected error\n"); // TODO: better return code Status = STATUS_UNSUCCESSFUL; goto FINISH; } } ip_set_option(Context->lwip_tcp_pcb, SOF_BROADCAST); + RELEASE_SERIAL_MUTEX(); NO_PCB: /* Failure would jump us beyond here, so being here means we succeeded in binding */ TCP_SET_STATE(TCP_STATE_BOUND, Context); Context->AddressFile = AddressFile; InterlockedIncrement(&AddressFile->ContextCount); - + Status = STATUS_SUCCESS; - + FINISH: return Status; } +/* This function does not require the Context mutex to be held. Holding the mutex while calling will + * succeed but will decrease performance, since the mutex will be acquired recursively. */ NTSTATUS -TcpIpDisassociateAddress( - _Inout_ PIRP Irp +DisassociateAddress( + PTCP_CONTEXT Context ) { - INT ContextCount; - + LONG ContextCount; + PADDRESS_FILE AddressFile; - PIO_STACK_LOCATION IrpSp; PIRP PendingIrp; PLIST_ENTRY Entry; PLIST_ENTRY Head; - PTCP_CONTEXT Context; PTCP_REQUEST Request; - - DPRINT("TcpIpDisassociateAddress(PIRP %p)\n", Irp); - - IrpSp = IoGetCurrentIrpStackLocation(Irp); - - /* Sanity checks */ - if (IrpSp->FileObject->FsContext2 != (PVOID)TDI_CONNECTION_FILE) - { - DPRINT("Disassociating something that is not a TCP Context\n"); - return STATUS_INVALID_PARAMETER; - } - Context = IrpSp->FileObject->FsContext; /* Immediately remove the Context's association with its Address File */ if (GetExclusiveContextAccess(Context) == FALSE) @@ -1081,19 +1175,18 @@ Request = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry); Entry = Entry->Flink; RemoveEntryList(&Request->ListEntry); - + /* If this is an IRP, block potential cancellations. */ if (Request->PayloadType == TCP_REQUEST_PAYLOAD_IRP) { PendingIrp = Request->Payload.PendingIrp; - DPRINT("Disassociating Context %p with outstanding IRP %p\n", Context, PendingIrp); IoSetCancelRoutine(PendingIrp, NULL); } - + /* Clean up the Request */ CleanupRequest(Request, STATUS_CANCELLED, Context); } - + /* Decrement the corresponding Address File's ContextCount, remove the Address File if needed */ if (AddressFile != NULL) { @@ -1103,8 +1196,29 @@ CloseAddress(AddressFile); } } - + return STATUS_SUCCESS; +} + +NTSTATUS +TcpIpDisassociateAddress( + _Inout_ PIRP Irp +) +{ + PIO_STACK_LOCATION IrpSp; + PTCP_CONTEXT Context; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + /* Sanity checks */ + if (IrpSp->FileObject->FsContext2 != (PVOID)TDI_CONNECTION_FILE) + { + DPRINT1("Disassociating something that is not a TCP Context\n"); + return STATUS_INVALID_PARAMETER; + } + Context = IrpSp->FileObject->FsContext; + + return DisassociateAddress(Context); } NTSTATUS @@ -1117,6 +1231,7 @@ KIRQL OldIrql; #endif NTSTATUS Status; + LONG ContextCount; PADDRESS_FILE AddressFile; PLIST_ENTRY Entry; @@ -1125,15 +1240,13 @@ PTCP_CONTEXT Context; PTCP_CONTEXT ListenContext; PTCP_REQUEST Request; - - DPRINT("TcpIpListen(PIRP %p)\n", Irp); - + IrpSp = IoGetCurrentIrpStackLocation(Irp); - + /* Grab TCP Context from IRP */ if (IrpSp->FileObject->FsContext2 != (PVOID)TDI_CONNECTION_FILE) { - DPRINT("Not a connection context\n"); + DPRINT1("Not a connection context\n"); return STATUS_INVALID_PARAMETER; } Context = IrpSp->FileObject->FsContext; @@ -1145,11 +1258,11 @@ } if (Context->TcpState != TCP_STATE_BOUND) { - DPRINT("Context is not a bound context\n"); + DPRINT1("Context is not a bound context\n"); ReleaseExclusiveContextAccess(Context); return STATUS_INVALID_PARAMETER; } - + AddressFile = Context->AddressFile; /* If there is already a listener on the address, this context is a dummy connection endpoint * used to poll/wait for new accepted connections. Check for queued accepted connections. If @@ -1157,7 +1270,14 @@ if (AddressFile->HasListener == TRUE) { ListenContext = AddressFile->Listener; - + if (GetExclusiveContextAccess(ListenContext) == FALSE) + { + DPRINT1("TDI_LISTEN on disassociated Listen Context? SNAFU.\n"); + ReleaseExclusiveContextAccess(ListenContext); + ReleaseExclusiveContextAccess(Context); + return STATUS_ADDRESS_CLOSED; + } + /* Check for queued accepted connections in the listener's Request queue */ Head = &ListenContext->RequestListHead; Entry = Head->Flink; @@ -1167,10 +1287,11 @@ if (Request->PendingMode == TCP_REQUEST_PENDING_ACCEPTED_CONNECTION) { RemoveEntryList(&Request->ListEntry); + ReleaseExclusiveContextAccess(ListenContext); goto CONNECTION_AVAILABLE; } } - + /* If there is no queued accepted connection, enqueue a Request with the new Context as the * payload, then enqueue the IRP. Finding a queued accepted connection jumps beyond here. */ EnqueueRequest( @@ -1179,76 +1300,120 @@ TCP_REQUEST_CANCEL_MODE_PRESERVE, TCP_REQUEST_PENDING_LISTEN_POLL, TCP_REQUEST_PAYLOAD_CONTEXT); - - /* Enqueue the IRP. First set the FsContext, since that is where PrepareIrpForCancel() gets - * the reference to the owning Context. */ - IrpSp->FileObject->FsContext = ListenContext; + + /* Enqueue the IRP */ Status = PrepareIrpForCancel( Irp, + ListenContext, CancelRequestRoutine, TCP_REQUEST_CANCEL_MODE_CLOSE, TCP_REQUEST_PENDING_LISTEN); - + + ReleaseExclusiveContextAccess(ListenContext); ReleaseExclusiveContextAccess(Context); return Status; - + CONNECTION_AVAILABLE: /* If there is a queued accepted connection, deallocate the Context that came with the IRP * and return the Context that is in the queue with IRP. */ #ifndef NDEBUG REMOVE_CONTEXT(Context); #endif - InterlockedDecrement(&Context->AddressFile->ContextCount); + ContextCount = InterlockedDecrement(&Context->AddressFile->ContextCount); + if (ContextCount < 1) + { + CloseAddress(Context->AddressFile); + } + Context->AddressFile = NULL; + ReleaseExclusiveContextAccess(Context); ExFreePoolWithTag(Context, TAG_TCP_CONTEXT); - + /* Set the IRP's FileObject to point to the queued Context. We also need to mark this * Context as created through a request by an upper level driver, since it replaces one that * actually was created that way. */ Context = Request->Payload.Context; TCP_SET_STATE(TCP_STATE_CONNECTED, Context); IrpSp->FileObject->FsContext = Context; - Context->CreatedWithoutRequest = TRUE; - + Context->ReferencedByUpperLayer = TRUE; + /* Inform lwIP that we accepted the connection */ + ACQUIRE_SERIAL_MUTEX(); tcp_accepted(ListenContext->lwip_tcp_pcb); - + RELEASE_SERIAL_MUTEX(); + ExFreePoolWithTag(Request, TAG_TCP_REQUEST); - + + /* main.c will call IoCompleteRequest() on this IRP */ + return STATUS_SUCCESS; + } + + /* If there is not already a listener on the address, create a Listen Context and enqueue the + * existing Context as a dummy Context. We will later perform our own disassociation and closure + * on the Listen Context. */ + /* Create context */ + ListenContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ListenContext), TAG_TCP_CONTEXT); + if (ListenContext == NULL) + { + DPRINT1("Not enough resources\n"); ReleaseExclusiveContextAccess(Context); - return STATUS_SUCCESS; - } + return STATUS_NO_MEMORY; + } +#ifndef NDEBUG + ADD_CONTEXT(ListenContext); +#endif + + /* Set initial values */ + ListenContext->AddressFile = AddressFile; + InitializeListHead(&ListenContext->RequestListHead); + ListenContext->ReferencedByUpperLayer = FALSE; + InitializeContextMutex(ListenContext); + InterlockedIncrement(&AddressFile->ContextCount); - /* If there is not already a listener on the address, call into lwIP to initiate Listen */ + /* Call into lwIP to initiate Listen */ #ifndef NDEBUG REMOVE_PCB(Context->lwip_tcp_pcb); #endif - Context->lwip_tcp_pcb = tcp_listen(Context->lwip_tcp_pcb); - if (Context->lwip_tcp_pcb == NULL) + ACQUIRE_SERIAL_MUTEX(); + ListenContext->lwip_tcp_pcb = tcp_listen(Context->lwip_tcp_pcb); + RELEASE_SERIAL_MUTEX(); + if (ListenContext->lwip_tcp_pcb == NULL) { DPRINT("Bind failed\n"); ReleaseExclusiveContextAccess(Context); return STATUS_INVALID_ADDRESS; } -#ifndef NDEBUG - ADD_PCB(Context->lwip_tcp_pcb); -#endif - + Context->lwip_tcp_pcb = NULL; +#ifndef NDEBUG + ADD_PCB(ListenContext->lwip_tcp_pcb); +#endif + /* Set lwIP callback information for new PCB */ - tcp_accept(Context->lwip_tcp_pcb, lwip_tcp_accept_callback); + ACQUIRE_SERIAL_MUTEX(); + tcp_arg(ListenContext->lwip_tcp_pcb, ListenContext); + tcp_accept(ListenContext->lwip_tcp_pcb, lwip_tcp_accept_callback); + RELEASE_SERIAL_MUTEX(); /* Mark the Address File as having a listener */ AddressFile->HasListener = TRUE; - AddressFile->Listener = Context; + AddressFile->Listener = ListenContext; - /* Mark IRP as pending and enqueue the Listen Request */ - DPRINT("Queueing TDI_LISTEN\n"); + /* Enqueue the dummy Context to receive new connections */ + EnqueueRequest( + Context, + ListenContext, + TCP_REQUEST_CANCEL_MODE_PRESERVE, + TCP_REQUEST_PENDING_LISTEN_POLL, + TCP_REQUEST_PAYLOAD_CONTEXT); + + /* Mark IRP as pending and enqueue the Listen Request on the Listen Context */ Status = PrepareIrpForCancel( Irp, + ListenContext, CancelRequestRoutine, TCP_REQUEST_CANCEL_MODE_CLOSE, TCP_REQUEST_PENDING_LISTEN); - TCP_SET_STATE(TCP_STATE_LISTENING, Context); - + TCP_SET_STATE(TCP_STATE_LISTENING, ListenContext); + ReleaseExclusiveContextAccess(Context); return Status; } @@ -1259,103 +1424,131 @@ ) { NTSTATUS Status; - + PIO_STACK_LOCATION IrpSp; PTCP_CONTEXT Context; PTDI_REQUEST_KERNEL_CONNECT RequestInfo; PTRANSPORT_ADDRESS RemoteTransportAddress; - + struct sockaddr *SocketAddressRemote; struct sockaddr_in * SocketAddressInRemote; - + err_t lwip_err; - - DPRINT("TcpIpConnect(PIRP %p)\n", Irp); - + IrpSp = IoGetCurrentIrpStackLocation(Irp); - - DPRINT("Sanity checks\n"); + /* Sanity checks */ if (IrpSp->FileObject->FsContext2 != (PVOID)TDI_CONNECTION_FILE) { - DPRINT("File object is not a connection context\n"); + DPRINT1("File object is not a connection context\n"); return STATUS_INVALID_PARAMETER; } Context = IrpSp->FileObject->FsContext; if (GetExclusiveContextAccess(Context) == FALSE) { - DPRINT("Context has been disassociated\n"); + DPRINT1("Context has been disassociated\n"); ReleaseExclusiveContextAccess(Context); return STATUS_ADDRESS_CLOSED; } if (Context->TcpState != TCP_STATE_BOUND) { - DPRINT("Connecting from unbound socket\n"); + DPRINT1("Connecting from unbound socket\n"); ReleaseExclusiveContextAccess(Context); return STATUS_INVALID_PARAMETER; } - - DPRINT("Extract remote address\n"); + /* Extract remote address to connect to */ RequestInfo = (PTDI_REQUEST_KERNEL_CONNECT)&IrpSp->Parameters; RemoteTransportAddress = RequestInfo->RequestConnectionInformation->RemoteAddress; SocketAddressRemote = (struct sockaddr *)&RemoteTransportAddress->Address[0]; SocketAddressInRemote = (struct sockaddr_in *)&SocketAddressRemote->sa_data; - - DPRINT("lwIP tcp_connect()\n"); + /* Call into lwIP to initiate Connect */ + ACQUIRE_SERIAL_MUTEX(); lwip_err = tcp_connect(Context->lwip_tcp_pcb, (ip_addr_t*)&SocketAddressInRemote->sin_addr.s_addr, SocketAddressInRemote->sin_port, lwip_tcp_connected_callback); + RELEASE_SERIAL_MUTEX(); switch (lwip_err) { case ERR_OK : - DPRINT("Queueing TDI_CONNECT\n"); /* If successful, enqueue the IRP, set the TCP State variable, and return */ Status = PrepareIrpForCancel( Irp, + Context, CancelRequestRoutine, TCP_REQUEST_CANCEL_MODE_ABORT, TCP_REQUEST_PENDING_CONNECT); TCP_SET_STATE(TCP_STATE_CONNECTING, Context); goto FINISH; case ERR_VAL : - DPRINT("lwip ERR_VAL\n"); + DPRINT1("lwip ERR_VAL\n"); Status = STATUS_INVALID_PARAMETER; goto FINISH; case ERR_ISCONN : - DPRINT("lwip ERR_ISCONN\n"); + DPRINT1("lwip ERR_ISCONN\n"); Status = STATUS_CONNECTION_ACTIVE; goto FINISH; case ERR_RTE : - DPRINT("lwip ERR_RTE\n"); + DPRINT1("lwip ERR_RTE\n"); Status = STATUS_NETWORK_UNREACHABLE; goto FINISH; case ERR_BUF : /* Use correct error once NDIS errors are included. * This return value means local port unavailable. */ - DPRINT("lwip ERR_BUF\n"); + DPRINT1("lwip ERR_BUF\n"); Status = STATUS_ADDRESS_ALREADY_EXISTS; goto FINISH; case ERR_USE : - DPRINT("lwip ERR_USE\n"); + DPRINT1("lwip ERR_USE\n"); Status = STATUS_CONNECTION_ACTIVE; goto FINISH; case ERR_MEM : - DPRINT("lwip ERR_MEM\n"); + DPRINT1("lwip ERR_MEM\n"); Status = STATUS_NO_MEMORY; goto FINISH; default : /* unknown return value */ - DPRINT("lwip unknown return code\n"); + DPRINT1("lwip unknown return code\n"); Status = STATUS_NOT_IMPLEMENTED; goto FINISH; } - + FINISH: ReleaseExclusiveContextAccess(Context); return Status; +} + +NTSTATUS +TcpIpDisconnect( + _Inout_ PIRP Irp +) +{ +#ifndef NDEBUG + INT i; + KIRQL OldIrql; +#endif + + PIO_STACK_LOCATION IrpSp; + PTCP_CONTEXT Context; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + /* Sanity checks. We do not acquire the Context mutex because TDI_DISCONNECT results from an + * IoCompleteRequest() called with the Context mutex held. */ + if (IrpSp->FileObject->FsContext2 != (PVOID)TDI_CONNECTION_FILE) + { + DPRINT1("Disconnection on something that is not a TCP Context\n"); + return STATUS_INVALID_PARAMETER; + } + + /* Mark the Context for disconnect. Do not shut down the PCB, because this function is called + * while another thread context holds the global MTSerialMutex. */ + Context = IrpSp->FileObject->FsContext; + TCP_SET_STATE(TCP_STATE_CLOSED, Context); + + return STATUS_SUCCESS; } NTSTATUS @@ -1365,15 +1558,13 @@ { PIO_STACK_LOCATION IrpSp; PTCP_CONTEXT Context; - - DPRINT1("TcpIpReceive(PIRP %p)\n", Irp); - + IrpSp = IoGetCurrentIrpStackLocation(Irp); - + /* Sanity checks */ if (IrpSp->FileObject->FsContext2 != (PVOID)TDI_CONNECTION_FILE) { - DPRINT("Received TDI_RECEIVE for something that is not a TCP Context\n"); + DPRINT1("Received TDI_RECEIVE for something that is not a TCP Context\n"); return STATUS_INVALID_PARAMETER; } Context = IrpSp->FileObject->FsContext; @@ -1385,25 +1576,25 @@ } if (!(Context->TcpState & TCP_STATE_CONNECTED)) { - DPRINT("TCP Context %p is in the wrong state for receiving data: %08x\n", + DPRINT1("TCP Context %p is in the wrong state for receiving data: %08x\n", Context, Context->TcpState); ReleaseExclusiveContextAccess(Context); return STATUS_ADDRESS_CLOSED; } - + /* No need to call into lwIP. The Receive callback should have been set when the connection was * established. */ - + /* Mark IRP as pending, and the TCP Context as Receiving */ - DPRINT("Queueing TDI_RECEIVE\n"); PrepareIrpForCancel( Irp, + Context, CancelRequestRoutine, TCP_REQUEST_CANCEL_MODE_PRESERVE, TCP_REQUEST_PENDING_RECEIVE); TCP_ADD_STATE(TCP_STATE_RECEIVING, Context); - + ReleaseExclusiveContextAccess(Context); return STATUS_PENDING; } @@ -1415,50 +1606,50 @@ { NTSTATUS Status; UINT SendBytes; - + PIO_STACK_LOCATION IrpSp; PTDI_REQUEST_KERNEL_SEND RequestInfo; PTCP_CONTEXT Context; PVOID Buffer; - + err_t lwip_err; - - DPRINT("TcpIpSend(PIRP %p)\n", Irp); - + IrpSp = IoGetCurrentIrpStackLocation(Irp); - + /* Sanity checks */ if (IrpSp->FileObject->FsContext2 != (PVOID)TDI_CONNECTION_FILE) { - DPRINT("Received TDI_SEND for something that is not a TCP Context\n"); + DPRINT1("Received TDI_SEND for something that is not a TCP Context\n"); return STATUS_INVALID_PARAMETER; } Context = IrpSp->FileObject->FsContext; if (GetExclusiveContextAccess(Context) == FALSE) { - DPRINT("Context has been disassociated\n"); + DPRINT1("Context has been disassociated\n"); ReleaseExclusiveContextAccess(Context); return STATUS_ADDRESS_CLOSED; } if (!(Context->TcpState & TCP_STATE_CONNECTED)) { - DPRINT("Attempting to send on Context at %p without an established connection\n", Context); + DPRINT1("Attempting to send on Context at %p without an established connection\n", Context); ReleaseExclusiveContextAccess(Context); return STATUS_ONLY_IF_CONNECTED; } - + /* Get send buffer and length */ NdisQueryBuffer(Irp->MdlAddress, &Buffer, &SendBytes); RequestInfo = (PTDI_REQUEST_KERNEL_SEND)&IrpSp->Parameters; - + /* If the Context is already servicing a Send request, do not initiate another one right now */ if (Context->TcpState & TCP_STATE_SENDING) { goto WAIT_TO_SEND; } - + /* Call into lwIP to initiate send */ + ACQUIRE_SERIAL_MUTEX(); lwip_err = tcp_write(Context->lwip_tcp_pcb, Buffer, RequestInfo->SendLength, 0); + RELEASE_SERIAL_MUTEX(); switch (lwip_err) { case ERR_OK: @@ -1466,36 +1657,35 @@ TCP_ADD_STATE(TCP_STATE_SENDING, Context); break; case ERR_MEM: - DPRINT("lwIP ERR_MEM\n"); + DPRINT1("lwIP ERR_MEM\n"); Status = STATUS_NO_MEMORY; goto FINISH; case ERR_ARG: - DPRINT("lwIP ERR_ARG\n"); + DPRINT1("lwIP ERR_ARG\n"); Status = STATUS_INVALID_PARAMETER; goto FINISH; case ERR_CONN: - DPRINT("lwIP ERR_CONN\n"); + DPRINT1("lwIP ERR_CONN\n"); Status = STATUS_CONNECTION_ACTIVE; goto FINISH; default: - DPRINT("Unknwon lwIP Error: %d\n", lwip_err); + DPRINT1("Unknwon lwIP Error: %d\n", lwip_err); Status = STATUS_NOT_IMPLEMENTED; goto FINISH; } - + WAIT_TO_SEND: - DPRINT("Queueing TDI_SEND\n"); Status = PrepareIrpForCancel( Irp, + Context, CancelRequestRoutine, TCP_REQUEST_CANCEL_MODE_PRESERVE, TCP_REQUEST_PENDING_SEND); - + FINISH: - ReleaseExclusiveContextAccess(Context); + ReleaseExclusiveContextAccess(Context); return Status; } - NTSTATUS AddressSetIpDontFragment( @@ -1587,6 +1777,9 @@ _Inout_ struct _DEVICE_OBJECT* DeviceObject, _Inout_ _IRQL_uses_cancel_ struct _IRP *Irp) { +#ifndef NDEBUG + INT i; +#endif PIO_STACK_LOCATION IrpSp; ADDRESS_FILE* AddressFile; RECEIVE_DATAGRAM_REQUEST* Request; @@ -1613,12 +1806,16 @@ NT_ASSERT(ListEntry != &AddressFile->RequestListHead); RemoveEntryList(&Request->ListEntry); - + KeReleaseSpinLock(&AddressFile->RequestLock, OldIrql); Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; +#ifndef NDEBUG + REMOVE_IRP(Irp); + REMOVE_IRPSP(IrpSp); +#endif IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); ExFreePoolWithTag(Request, TAG_DGRAM_REQST); @@ -1628,6 +1825,10 @@ TcpIpReceiveDatagram( _Inout_ PIRP Irp) { +#ifndef NDEBUG + KIRQL OldIrql; + INT i; +#endif PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); ADDRESS_FILE *AddressFile; RECEIVE_DATAGRAM_REQUEST* Request = NULL; @@ -1701,6 +1902,10 @@ if (Request) ExFreePoolWithTag(Request, TAG_DGRAM_REQST); Irp->IoStatus.Status = Status; +#ifndef NDEBUG + REMOVE_IRP(Irp); + REMOVE_IRPSP(IrpSp); +#endif IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); return Status; } @@ -1709,6 +1914,10 @@ TcpIpSendDatagram( _Inout_ PIRP Irp) { +#ifndef NDEBUG + KIRQL OldIrql; + INT i; +#endif PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); ADDRESS_FILE *AddressFile; PTDI_REQUEST_KERNEL_SENDDG RequestInfo; @@ -1823,19 +2032,19 @@ break; case ERR_MEM: case ERR_BUF: - DPRINT("Received ERR_MEM from lwip.\n"); + DPRINT1("Received ERR_MEM from lwip.\n"); Status = STATUS_INSUFFICIENT_RESOURCES; break; case ERR_RTE: - DPRINT("Received ERR_RTE from lwip.\n"); + DPRINT1("Received ERR_RTE from lwip.\n"); Status = STATUS_INVALID_ADDRESS; break; case ERR_VAL: - DPRINT("Received ERR_VAL from lwip.\n"); + DPRINT1("Received ERR_VAL from lwip.\n"); Status = STATUS_INVALID_PARAMETER; break; default: - DPRINT("Received error %d from lwip.\n", lwip_error); + DPRINT1("Received error %d from lwip.\n", lwip_error); Status = STATUS_UNEXPECTED_NETWORK_ERROR; } @@ -1843,11 +2052,17 @@ if (p) pbuf_free(p); Irp->IoStatus.Status = Status; +#ifndef NDEBUG + REMOVE_IRP(Irp); + REMOVE_IRPSP(IrpSp); +#endif IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); return Status; } -/* If the PCB is deallocated, set the PCB pointer to NULL before calling */ +/* Acquire Context mutex before calling. If the PCB is deallocated, also set the PCB pointer to NULL + * before calling. */ +VOID ProcessPCBError( PTCP_CONTEXT Context, ULONG TcpState) @@ -1856,31 +2071,27 @@ PLIST_ENTRY Entry; PLIST_ENTRY Head; PTCP_REQUEST Request; - + /* Set the Context's State to indicate it is no longer active */ TCP_SET_STATE(TcpState, Context); - + /* Walk the Context's list of pending requests and finish them */ Head = &Context->RequestListHead; Entry = Head->Flink; while (Entry != Head) { -#ifndef NDEBUG - DPRINT("Closing Context with outstanding Requests\n"); -#endif /* Extract Request */ Request = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry); - + /* Block potential cancellations */ Irp = Request->Payload.PendingIrp; IoSetCancelRoutine(Irp, NULL); - + /* Dequeue Request and increment list walk */ Entry = Entry->Flink; RemoveEntryList(&Request->ListEntry); - + /* Complete the IRP, deallocate the Request, and deallocate the lwIP PCB if necessary */ - DPRINT("Dequeueing Pending Request from %p\n", Context); Irp->IoStatus.Information = 0; CleanupRequest(Request, STATUS_CANCELLED, Context); } @@ -1893,52 +2104,50 @@ ) { ULONG TcpState; - + PTCP_CONTEXT Context; - - DPRINT("lwip_tcp_err_callback\n"); - + /* Interpret lwIP error */ // TODO: detailed NTSTATUS codes switch (err) { case ERR_ABRT : - DPRINT("lwIP socket aborted\n"); + DPRINT1("lwIP socket aborted\n"); TcpState = TCP_STATE_ABORTED; break; case ERR_RST : /* This is the only case that indicates the lwIP PCB still exists */ - DPRINT("lwIP socket reset\n"); + DPRINT1("lwIP socket reset\n"); TcpState = TCP_STATE_CLOSED; goto RETAIN_PCB; case ERR_CLSD : - DPRINT("lwIP socket closed\n"); + DPRINT1("lwIP socket closed\n"); TcpState = TCP_STATE_CLOSED; break; case ERR_CONN : - DPRINT("lwIP connection failed\n"); + DPRINT1("lwIP connection failed\n"); TcpState = TCP_STATE_CLOSED; break; case ERR_ARG : - DPRINT("lwIP invalid arguments\n"); + DPRINT1("lwIP invalid arguments\n"); TcpState = TCP_STATE_ABORTED; break; case ERR_IF : - DPRINT("Low-level error\n"); + DPRINT1("Low-level error\n"); TcpState = TCP_STATE_ABORTED; break; default : - DPRINT("Unsupported lwIP error code: %d\n", err); + DPRINT1("Unsupported lwIP error code: %d\n", err); TcpState = TCP_STATE_ABORTED; break; } - + Context = (PTCP_CONTEXT)arg; if (Context == NULL) { return; } - + GetExclusiveContextAccess(Context); Context->lwip_tcp_pcb = NULL; RETAIN_PCB: @@ -1958,24 +2167,22 @@ PLIST_ENTRY Entry; PTCP_CONTEXT Context; PTCP_REQUEST Request; - - DPRINT("lwip_tcp_connected_callback\n"); - + /* lwIP currently never sends anything other than ERR_OK here */ - + Context = (PTCP_CONTEXT)arg; GetExclusiveContextAccess(Context); - + /* Sanity checks */ if (Context->TcpState != TCP_STATE_CONNECTING) { - DPRINT("Callback on a context that did not initiate a connection\n"); + DPRINT1("Callback on a context that did not initiate a connection\n"); ReleaseExclusiveContextAccess(Context); return ERR_ARG; } if (Context->lwip_tcp_pcb != tpcb) { - DPRINT("Connected PCB mismatch\n"); + DPRINT1("Connected PCB mismatch\n"); ReleaseExclusiveContextAccess(Context); return ERR_ARG; } @@ -1983,35 +2190,33 @@ Entry = RemoveHeadList(&Context->RequestListHead); if (Entry == &Context->RequestListHead) { - DPRINT("No matching Connect Request found\n"); + DPRINT1("No matching Connect Request found\n"); ReleaseExclusiveContextAccess(Context); return ERR_ARG; } - + Request = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry); Irp = Request->Payload.PendingIrp; - + /* Block cancellations */ IoSetCancelRoutine(Irp, NULL); - + /* One last sanity check */ if (Request->PendingMode != TCP_REQUEST_PENDING_CONNECT) { - DPRINT("Pending Request is not a Connect request. This should never happen.\n"); + DPRINT1("Pending Request is not a Connect request. This should never happen.\n"); Irp->IoStatus.Information = 0; - DPRINT("Dequeueing TDI_CONNECT\n"); CleanupRequest(Request, STATUS_CANCELLED, Context); ReleaseExclusiveContextAccess(Context); return ERR_CONN; } - + /* Complete the Request, set TCP State variable, and set callback information */ - DPRINT("Dequeueing TDI_CONNECT\n"); TCP_SET_STATE(TCP_STATE_CONNECTED, Context); tcp_sent(Context->lwip_tcp_pcb, lwip_tcp_sent_callback); tcp_recv(Context->lwip_tcp_pcb, lwip_tcp_receive_callback); CleanupRequest(Request, STATUS_SUCCESS, Context); - + ReleaseExclusiveContextAccess(Context); return ERR_OK; } @@ -2029,7 +2234,7 @@ KIRQL OldIrql; #endif NTSTATUS Status; - + PIO_STACK_LOCATION IrpSp; PIRP Irp; PLIST_ENTRY Entry; @@ -2039,19 +2244,16 @@ PTCP_REQUEST CurrentRequest; PTCP_REQUEST DummyRequest; PTCP_REQUEST Request; - - DPRINT("lwip_tcp_accept_callback\n"); - + /* lwIP currently never sends anything other than ERR_OK here */ - + Context = (PTCP_CONTEXT)arg; GetExclusiveContextAccess(Context); - + /* Sanity check */ - DPRINT("Sanity Checks\n"); if (!(Context->TcpState & TCP_STATE_LISTENING)) { - DPRINT("lwIP sending Accept event to non-listening TCP Context\n"); + DPRINT1("lwIP sending Accept event to non-listening TCP Context\n"); #ifndef NDEBUG REMOVE_PCB(Context->lwip_tcp_pcb); #endif @@ -2060,9 +2262,8 @@ ReleaseExclusiveContextAccess(Context); return ERR_CLSD; } - + /* Look for a Listen request and an available dummy Context */ - DPRINT("Look for a Listen request\n"); Head = &Context->RequestListHead; NewContext = NULL; Request = NULL; @@ -2070,18 +2271,17 @@ while (Entry != Head) { // TODO: optimize checking logic - + CurrentRequest = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry); if ((CurrentRequest->PendingMode == TCP_REQUEST_PENDING_LISTEN) && (Request == NULL)) { - DPRINT("Found a Listen\n"); /* This is the Listen request we are looking for. Immediately block cancellations, then * dequeue the Request. */ Irp = CurrentRequest->Payload.PendingIrp; IoSetCancelRoutine(Irp, NULL); RemoveEntryList(&CurrentRequest->ListEntry); Request = CurrentRequest; - + /* If we have already found a dummy Context, associate it with the Established PCB. */ if (NewContext != NULL) { @@ -2093,13 +2293,12 @@ else if ((CurrentRequest->PendingMode == TCP_REQUEST_PENDING_LISTEN_POLL) && (NewContext == NULL)) { - DPRINT("Found a dummy\n"); /* This is a dummy Context we can use instead of creating a new one. Store a reference * to it. No need to acquire exclusive access to this Context because this is the only * existing pointer to it at this moment. */ NewContext = CurrentRequest->Payload.Context; DummyRequest = CurrentRequest; - + /* If we have already found a Listen request, we still must associate this Context with * the Established PCB before completing the Request. */ if (Request != NULL) @@ -2111,16 +2310,15 @@ } Entry = Entry->Flink; } - + /* We need a Context to store the Established PCB in. If the list does not contain a dummy * Context, we need to create a new one. */ if (NewContext == NULL) { - DPRINT("Allocate and intialize new TCP Context\n"); NewContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewContext), TAG_TCP_CONTEXT); if (NewContext == NULL) { - DPRINT("Not enough resources\n"); + DPRINT1("Not enough resources\n"); ReleaseExclusiveContextAccess(Context); return ERR_MEM; } @@ -2129,14 +2327,13 @@ #endif NewContext->AddressFile = Context->AddressFile; InitializeListHead(&NewContext->RequestListHead); - NewContext->CreatedWithoutRequest = TRUE; + NewContext->ReferencedByUpperLayer = FALSE; InitializeContextMutex(NewContext); - - /* Increment the Address File's Context reference count and set PCB callback info */ - DPRINT("Increment Address File's Context count and set PCB callback information\n"); + + /* Increment the Address File's Context reference count */ InterlockedIncrement(&NewContext->AddressFile->ContextCount); } - + CONTEXT_FOUND: /* Associate the new Context and the Established PCB with each other */ #ifndef NDEBUG @@ -2147,43 +2344,43 @@ tcp_err(NewContext->lwip_tcp_pcb, lwip_tcp_err_callback); tcp_sent(NewContext->lwip_tcp_pcb, lwip_tcp_sent_callback); tcp_recv(NewContext->lwip_tcp_pcb, lwip_tcp_receive_callback); - + /* If we found a Listen request, complete it. */ if (Request != NULL) { - DPRINT("Completing Listen\n"); /* Store new Context information */ TCP_SET_STATE(TCP_STATE_CONNECTED, NewContext); IrpSp = IoGetCurrentIrpStackLocation(Irp); IrpSp->FileObject->FsContext = NewContext; IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONNECTION_FILE; - + /* Finish the Request */ + NewContext->ReferencedByUpperLayer = TRUE; CleanupRequest(Request, STATUS_SUCCESS, Context); - + /* Notify the listening lwIP PCB that we accepted the connection */ tcp_accepted(Context->lwip_tcp_pcb); - + ReleaseExclusiveContextAccess(Context); return ERR_OK; } - - DPRINT("Enqueueing prepared Context %p\n", NewContext); + /* If we did not find a Listen request, we need to enqueue the new Context. The next TDI_LISTEN * will find it and complete without pending. */ TCP_SET_STATE(TCP_STATE_BOUND, NewContext); - Status = EnqueueRequest(NewContext, + Status = EnqueueRequest( + NewContext, Context, TCP_REQUEST_CANCEL_MODE_PRESERVE, TCP_REQUEST_PENDING_ACCEPTED_CONNECTION, TCP_REQUEST_PAYLOAD_CONTEXT); if (Status != STATUS_SUCCESS) { - DPRINT("Ran out of resources trying to enqueue a connected Context\n"); + DPRINT1("Ran out of resources trying to enqueue a connected Context\n"); ReleaseExclusiveContextAccess(Context); return ERR_MEM; } - + ReleaseExclusiveContextAccess(Context); return ERR_OK; } @@ -2200,25 +2397,23 @@ INT CopiedLength; INT RemainingDestBytes; UCHAR *CurrentDestLocation; - + PIRP Irp; PLIST_ENTRY Head; PLIST_ENTRY Entry; PNDIS_BUFFER Buffer; PTCP_CONTEXT Context; PTCP_REQUEST Request; - + struct pbuf *next; - - DPRINT("lwip_tcp_receive_callback\n"); - + /* lwIP currently never sends anything other than ERR_OK here */ - + Context = (PTCP_CONTEXT)arg; - + /* Get exclusive access to the Context */ GetExclusiveContextAccess(Context); - + /* If the buffer is NULL, the PCB has been closed */ if (p == NULL) { @@ -2227,21 +2422,21 @@ ReleaseExclusiveContextAccess(Context); return ERR_OK; } - + /* Sanity checks */ if (!(Context->TcpState & TCP_STATE_RECEIVING)) { - DPRINT("Receive callback on Context that is not currently receiving\n"); + DPRINT1("Receive callback on Context that is not currently receiving\n"); ReleaseExclusiveContextAccess(Context); return ERR_ARG; } if (Context->lwip_tcp_pcb != tpcb) { - DPRINT("Receive PCB mismatch\n"); + DPRINT1("Receive PCB mismatch\n"); ReleaseExclusiveContextAccess(Context); return ERR_ARG; } - + /* Walk the Request list for the matching Receive request */ Head = &Context->RequestListHead; Entry = Head->Flink; @@ -2259,16 +2454,16 @@ } Entry = Entry->Flink; } - DPRINT("Failed to find a pending Receive\n"); + DPRINT1("Failed to find a pending Receive\n"); TCP_RMV_STATE(TCP_STATE_RECEIVING, Context); ReleaseExclusiveContextAccess(Context); return ERR_ARG; - + FOUND: /* Get buffer pointers to write to */ Buffer = (PNDIS_BUFFER)Irp->MdlAddress; NdisQueryBuffer(Buffer, &CurrentDestLocation, &RemainingDestBytes); - + /** * Copy the data from the pbuf to the NDIS Buffer **/ @@ -2277,12 +2472,12 @@ while (RemainingDestBytes > p->len) { RtlCopyMemory(CurrentDestLocation, p->payload, p->len); - + /* Update pointers and byte count */ CopiedLength += p->len; CurrentDestLocation += p->len; RemainingDestBytes -= p->len; - + /* If there is still data left, go to the next pbuf. Otherwise, we are done copying. */ if (p->next != NULL) { @@ -2300,11 +2495,11 @@ * final copy to top off the NDIS Buffer, then update the byte count. */ RtlCopyMemory(CurrentDestLocation, p->payload, RemainingDestBytes); CopiedLength += RemainingDestBytes; - + COPY_DONE: /* Inform lwIP of how much data we copied */ tcp_recved(Context->lwip_tcp_pcb, CopiedLength); - + /* Check for other pending Receive requests. If there are none, clear the Receive TCP State bit. * Otherwise, leave the state variable alone. */ Entry = Head->Flink; @@ -2319,13 +2514,12 @@ } } TCP_RMV_STATE(TCP_STATE_RECEIVING, Context); - + STILL_PENDING: /* Clean up the Request struct and the IRP */ Irp->IoStatus.Information = CopiedLength; - DPRINT("Dequeueing TDI_RECEIVE\n"); CleanupRequest(Request, STATUS_SUCCESS, Context); - + ReleaseExclusiveContextAccess(Context); return ERR_OK; } @@ -2343,57 +2537,54 @@ PLIST_ENTRY Head; PTCP_CONTEXT Context; PTCP_REQUEST Request; - - DPRINT("lwip_tcp_sent_callback\n"); - + Context = (PTCP_CONTEXT)arg; - + /* Get exclusive access to the Context */ GetExclusiveContextAccess(Context); - + /* Sanity check */ if (!(Context->TcpState & TCP_STATE_SENDING)) { - DPRINT("Callback on a connection that is not sending anything\n"); + DPRINT1("Callback on a connection that is not sending anything\n"); ReleaseExclusiveContextAccess(Context); return ERR_ARG; } - + /* Walk Request list for the first Send request */ Head = &Context->RequestListHead; Entry = Head->Flink; while (Entry != Head) { Request = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry); - + /* Jump to handler when Request found */ if (Request->PendingMode == TCP_REQUEST_PENDING_SEND) { /* Immediately block any cancellations */ Irp = Request->Payload.PendingIrp; IoSetCancelRoutine(Irp, NULL); - + /* Dequeue the entry and jump to handler */ RemoveEntryList(&Request->ListEntry); goto FOUND; } - + Entry = Entry->Flink; } - + /* Being here means we walked the entire list without finding a Send request. We should clear * the TCP State variable SENDING bit. */ - DPRINT("Callback on Context with no outstanding Send requests\n"); + DPRINT1("Callback on Context with no outstanding Send requests\n"); TCP_RMV_STATE(TCP_STATE_SENDING, Context); ReleaseExclusiveContextAccess(Context); return ERR_ARG; - + FOUND: /* Complete the Request */ - DPRINT("Dequeueing TDI_SEND\n"); Irp->IoStatus.Information = len; CleanupRequest(Request, STATUS_SUCCESS, Context); - + ReleaseExclusiveContextAccess(Context); return ERR_OK; } Modified: branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/drivers/ne…
============================================================================== --- branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h [iso-8859-1] (original) +++ branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h [iso-8859-1] Wed Aug 3 19:57:20 2016 @@ -28,13 +28,116 @@ #define TCP_STATE_DISASSOCIATED 0x1 << 8 #define TCP_STATE_CLOSED 0x1 << 9 +//#define TCPIP_NDEBUG +#ifndef TCPIP_NDEBUG +KSPIN_LOCK IRPArrayLock; +PIRP IRPArray[16]; +volatile long int IRPCount; + +#define ADD_IRP(Irp) \ + KeAcquireSpinLock(&IRPArrayLock, &OldIrql); \ + IRPArray[IRPCount] = Irp; \ + IRPCount++; \ + KeReleaseSpinLock(&IRPArrayLock, OldIrql) + +#define ADD_IRP_DPC(Irp) \ + KeAcquireSpinLockAtDpcLevel(&IRPArrayLock); \ + IRPArray[IRPCount] = Irp; \ + IRPCount++; \ + KeReleaseSpinLockFromDpcLevel(&IRPArrayLock) + +#define REMOVE_IRP(Irp) \ + KeAcquireSpinLock(&IRPArrayLock, &OldIrql); \ + for (i = 0; i < IRPCount; i++) \ + { \ + if (Irp == IRPArray[i]) \ + { \ + IRPArray[i] = NULL; \ + } \ + if (IRPArray[i] == NULL) \ + { \ + IRPArray[i] = IRPArray[i+1]; \ + IRPArray[i+1] = NULL; \ + } \ + } \ + IRPCount--; \ + KeReleaseSpinLock(&IRPArrayLock, OldIrql) + +#define REMOVE_IRP_DPC(Irp) \ + KeAcquireSpinLockAtDpcLevel(&IRPArrayLock); \ + for (i = 0; i < IRPCount; i++) \ + { \ + if (Irp == IRPArray[i]) \ + { \ + IRPArray[i] = NULL; \ + } \ + if (IRPArray[i] == NULL) \ + { \ + IRPArray[i] = IRPArray[i+1]; \ + IRPArray[i+1] = NULL; \ + } \ + } \ + IRPCount--; \ + KeReleaseSpinLockFromDpcLevel(&IRPArrayLock) + +KSPIN_LOCK IRPSPArrayLock; +PIO_STACK_LOCATION IRPSPArray[16]; +volatile long int IRPSPCount; + +#define ADD_IRPSP(IrpSp) \ + KeAcquireSpinLock(&IRPSPArrayLock, &OldIrql); \ + IRPSPArray[IRPSPCount] = IrpSp; \ + IRPSPCount++; \ + KeReleaseSpinLock(&IRPSPArrayLock, OldIrql) + +#define ADD_IRPSP_DPC(IrpSp) \ + KeAcquireSpinLockAtDpcLevel(&IRPSPArrayLock); \ + IRPSPArray[IRPSPCount] = IrpSp; \ + IRPSPCount++; \ + KeReleaseSpinLockFromDpcLevel(&IRPSPArrayLock) + +#define REMOVE_IRPSP(IrpSp) \ + KeAcquireSpinLock(&IRPSPArrayLock, &OldIrql); \ + for (i = 0; i < IRPSPCount; i++) \ + { \ + if (IrpSp == IRPSPArray[i]) \ + { \ + IRPSPArray[i] = NULL; \ + } \ + if (IRPSPArray[i] == NULL) \ + { \ + IRPSPArray[i] = IRPSPArray[i+1]; \ + IRPSPArray[i+1] = NULL; \ + } \ + } \ + IRPSPCount--; \ + KeReleaseSpinLock(&IRPSPArrayLock, OldIrql) + +#define REMOVE_IRPSP_DPC(IrpSp) \ + KeAcquireSpinLockAtDpcLevel(&IRPSPArrayLock); \ + for (i = 0; i < IRPSPCount; i++) \ + { \ + if (IrpSp == IRPSPArray[i]) \ + { \ + IRPSPArray[i] = NULL; \ + } \ + if (IRPSPArray[i] == NULL) \ + { \ + IRPSPArray[i] = IRPSPArray[i+1]; \ + IRPSPArray[i+1] = NULL; \ + } \ + } \ + IRPSPCount--; \ + KeReleaseSpinLockFromDpcLevel(&IRPSPArrayLock) +#endif + struct _TCP_CONTEXT; typedef struct _TCP_CONTEXT TCP_CONTEXT, *PTCP_CONTEXT; typedef struct _ADDRESS_FILE { LIST_ENTRY ListEntry; LONG RefCount; - LONG ContextCount; + volatile long ContextCount; IPPROTO Protocol; TDI_ADDRESS_IP Address; struct netif *NetInterface; @@ -56,9 +159,9 @@ PADDRESS_FILE AddressFile; LIST_ENTRY RequestListHead; struct tcp_pcb* lwip_tcp_pcb; - BOOLEAN CreatedWithoutRequest; + BOOLEAN ReferencedByUpperLayer; HANDLE MutexOwner; - volatile long int MutexDepth; + volatile long MutexDepth; }; typedef struct _TCP_REQUEST { @@ -106,6 +209,11 @@ ); NTSTATUS +TcpIpDisconnect( + _Inout_ PIRP Irp +); + +NTSTATUS TcpIpAssociateAddress( _Inout_ PIRP Irp ); @@ -132,7 +240,7 @@ NTSTATUS TcpIpSend( _Inout_ PIRP Irp); - + NTSTATUS TcpIpSendDatagram( _Inout_ PIRP Irp); Modified: branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/interface.c URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/drivers/ne…
============================================================================== --- branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/interface.c [iso-8859-1] (original) +++ branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/interface.c [iso-8859-1] Wed Aug 3 19:57:20 2016 @@ -203,6 +203,7 @@ IP4_ADDR(&GatewayAddr, 127,0,0,1); IP4_ADDR(&IpAddr, 127,0,0,1); IP4_ADDR(&SubnetMask, 255,0,0,0); + ACQUIRE_SERIAL_MUTEX(); lwip_error = netifapi_netif_add( &LoopbackInterface->lwip_netif, &IpAddr, @@ -214,10 +215,12 @@ if (lwip_error != ERR_OK) { ExFreePoolWithTag(LoopbackInterface, TAG_INTERFACE); + RELEASE_SERIAL_MUTEX(); return STATUS_INSUFFICIENT_RESOURCES; } netifapi_netif_set_up(&LoopbackInterface->lwip_netif); + RELEASE_SERIAL_MUTEX(); /* Add this interface into the entities DB */ InsertEntityInstance(CL_NL_ENTITY, &LoopbackInterface->ClNlInstance); Modified: branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/main.c URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/drivers/ne…
============================================================================== --- branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/main.c [iso-8859-1] (original) +++ branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/main.c [iso-8859-1] Wed Aug 3 19:57:20 2016 @@ -38,7 +38,8 @@ #define DD_IP_DEVICE_NAME L"\\Device\\Ip" #define DD_RAWIP_DEVICE_NAME L"\\Device\\RawIp" -/* This is a small utility which get the IPPROTO_* constant from the device object this driver was passed */ +/* This is a small utility which get the IPPROTO_* constant from the device object this driver was + * passed */ static IPPROTO ProtocolFromIrp( @@ -98,6 +99,7 @@ /* Initialize the lwip library */ tcpip_init(NULL, NULL); + RELEASE_SERIAL_MUTEX(); /* Create the device objects */ Status = IoCreateDevice( @@ -207,14 +209,23 @@ _Inout_ struct _IRP *Irp ) { +#ifndef NDEBUG + KIRQL OldIrql; + INT i; +#endif NTSTATUS Status; PFILE_FULL_EA_INFORMATION FileInfo; IPPROTO Protocol; // ADDRESS_FILE *AddressFile; - + // ULONG *temp; - + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + +#ifndef NDEBUG + ADD_IRP(Irp); + ADD_IRPSP(IrpSp); +#endif /* Grab the info describing the file */ FileInfo = Irp->AssociatedIrp.SystemBuffer; @@ -227,14 +238,14 @@ Status = STATUS_SUCCESS; goto Quickie; } - + /* Validate it */ switch (FileInfo->EaNameLength) { case TDI_TRANSPORT_ADDRESS_LENGTH: { PTA_IP_ADDRESS Address; - + DPRINT1("TCPIP Create Transport Address\n"); if (strncmp(&FileInfo->EaName[0], TdiTransportAddress, TDI_TRANSPORT_ADDRESS_LENGTH) != 0) @@ -284,17 +295,17 @@ case TDI_CONNECTION_CONTEXT_LENGTH: { PTA_IP_ADDRESS Address; - + DPRINT1("TCPIP Create connection Context\n"); - + if (strncmp(&FileInfo->EaName[0], TdiConnectionContext, TDI_CONNECTION_CONTEXT_LENGTH) != 0) { DPRINT1("TCPIP: Should maybe open file %*s.\n", FileInfo->EaNameLength, &FileInfo->EaName[0]); return STATUS_INVALID_PARAMETER; } - + Address = (PTA_IP_ADDRESS)(&FileInfo->EaName[FileInfo->EaNameLength + 1]); - + /* Get the protocol this address will be created for. */ Protocol = ProtocolFromIrp(DeviceObject, IrpSp); if (Protocol == (IPPROTO)-1) @@ -302,12 +313,12 @@ Status = STATUS_INVALID_PARAMETER; goto Quickie; } - + /* temp = (ULONG*)Protocol; DPRINT1("\n Protocol: %08x\n", temp); - + temp = (ULONG*)Address;*/ - + /* All good. */ /* DPRINT1("\n PTA_IP_ADDRESS dump before\n %08x %08x %08x %08x\n %08x %08x %08x %08x\n", temp[7], temp[6], temp[5], temp[4], @@ -332,6 +343,10 @@ } else { +#ifndef NDEBUG + REMOVE_IRP(Irp); + REMOVE_IRPSP(IrpSp); +#endif IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); } @@ -346,11 +361,20 @@ _Inout_ struct _IRP *Irp ) { +#ifndef NDEBUG + KIRQL OldIrql; + INT i; +#endif PIO_STACK_LOCATION IrpSp; NTSTATUS Status; ULONG_PTR FileType; - + IrpSp = IoGetCurrentIrpStackLocation(Irp); + +#ifndef NDEBUG + ADD_IRP(Irp); + ADD_IRPSP(IrpSp); +#endif FileType = (ULONG_PTR)IrpSp->FileObject->FsContext2; @@ -367,7 +391,7 @@ Status = TcpIpCloseAddress(IrpSp->FileObject->FsContext); break; case TDI_CONNECTION_FILE: - DPRINT1("TCPIP Close Transport Address\n"); + DPRINT1("TCPIP Close Connection File\n"); if (!IrpSp->FileObject->FsContext) { DPRINT1("TCPIP: Got a close request without a file to close!\n"); @@ -390,8 +414,12 @@ Quickie: Irp->IoStatus.Status = Status; +#ifndef NDEBUG + REMOVE_IRP(Irp); + REMOVE_IRPSP(IrpSp); +#endif IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); - + return Status; } @@ -403,14 +431,23 @@ _Inout_ struct _IRP *Irp ) { +#ifndef NDEBUG + KIRQL OldIrql; + INT i; +#endif NTSTATUS Status; PIO_STACK_LOCATION IrpSp; PTCP_CONTEXT Context; PADDRESS_FILE AddressFile; DPRINT1("TcpIpDispatchInternal\n"); - + IrpSp = IoGetCurrentIrpStackLocation(Irp); + +#ifndef NDEBUG + ADD_IRP(Irp); + ADD_IRPSP(IrpSp); +#endif switch ((ULONG)IrpSp->FileObject->FsContext2) { @@ -425,7 +462,7 @@ DPRINT1("Unknown FileObject type\n"); break; } - + switch (IrpSp->MinorFunction) { case TDI_RECEIVE: @@ -496,7 +533,8 @@ case TDI_DISCONNECT: DPRINT1("TCPIP: TDI_DISCONNECT!\n"); - Status = STATUS_NOT_IMPLEMENTED; + Status = TcpIpDisconnect(Irp); + DPRINT("TcpIpDisconnect() Returned\n"); break; case TDI_ASSOCIATE_ADDRESS: @@ -533,7 +571,7 @@ DPRINT1("TCPIP: Unknown internal IOCTL: 0x%x.\n", IrpSp->MinorFunction); Status = STATUS_NOT_IMPLEMENTED; } - + FINISH: Irp->IoStatus.Status = Status; if (Status == STATUS_PENDING) @@ -542,6 +580,10 @@ } else { +#ifndef NDEBUG + REMOVE_IRP(Irp); + REMOVE_IRPSP(IrpSp); +#endif IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); } @@ -558,7 +600,7 @@ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp; - + IrpSp = IoGetCurrentIrpStackLocation(Irp); Irp->IoStatus.Information = 0; Modified: branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/arch/sys_arch.h URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/sdk/lib/dr…
============================================================================== --- branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/arch/sys_arch.h [iso-8859-1] (original) +++ branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/arch/sys_arch.h [iso-8859-1] Wed Aug 3 19:57:20 2016 @@ -39,5 +39,4 @@ sys_arch_unprotect(sys_prot_t lev); void -sys_shutdown(void); - +sys_shutdown(void); Modified: branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/lwip/tcp.h URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/sdk/lib/dr…
============================================================================== --- branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/lwip/tcp.h [iso-8859-1] (original) +++ branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/lwip/tcp.h [iso-8859-1] Wed Aug 3 19:57:20 2016 @@ -368,9 +368,23 @@ err_t tcp_output (struct tcp_pcb *pcb); +/** + * REACT_OS Global Mutex + * Serializes all kernel network activity to circumvent lwIP core's lack of thread-safety. + */ +KMUTEX MTSerialMutex; + +#define ACQUIRE_SERIAL_MUTEX() \ + DPRINT("Acquiring MTSerialMutex on thread %p\n", PsGetCurrentThreadId()); \ + KeWaitForMutexObject(&MTSerialMutex, Executive, KernelMode, FALSE, NULL); \ + DPRINT("MTSerialMutex acquired on thread %p\n", PsGetCurrentThreadId()) + +#define RELEASE_SERIAL_MUTEX() \ + DPRINT("Releasing MTSerialMutex on thread %p\n", PsGetCurrentThreadId()); \ + KeReleaseMutex(&MTSerialMutex, FALSE); \ + DPRINT("MTSerialMutex released on thread %p\n", PsGetCurrentThreadId()) const char* tcp_debug_state_str(enum tcp_state s); - #ifdef __cplusplus } Modified: branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/lwip/tcpip.h URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/sdk/lib/dr…
============================================================================== --- branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/lwip/tcpip.h [iso-8859-1] (original) +++ branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/lwip/tcpip.h [iso-8859-1] Wed Aug 3 19:57:20 2016 @@ -158,6 +158,8 @@ } msg; }; +extern KMUTEX MTSerialMutex; + #ifdef __cplusplus } #endif Modified: branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/sys_arch.c URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/sdk/lib/dr…
============================================================================== --- branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/sys_arch.c [iso-8859-1] (original) +++ branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/sys_arch.c [iso-8859-1] Wed Aug 3 19:57:20 2016 @@ -1,3 +1,5 @@ +#include <ntifs.h> + #include "lwip/sys.h" #include "lwip/tcp.h" @@ -95,6 +97,7 @@ KeQuerySystemTime(&PreWaitTime); + RELEASE_SERIAL_MUTEX(); Status = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, @@ -103,6 +106,7 @@ FALSE, timeout != 0 ? &LargeTimeout : NULL, NULL); + ACQUIRE_SERIAL_MUTEX(); if (Status == STATUS_WAIT_0) { KeQuerySystemTime(&PostWaitTime); @@ -190,6 +194,7 @@ KeQuerySystemTime(&PreWaitTime); + RELEASE_SERIAL_MUTEX(); Status = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, @@ -198,6 +203,7 @@ FALSE, timeout != 0 ? &LargeTimeout : NULL, NULL); + ACQUIRE_SERIAL_MUTEX(); if (Status == STATUS_WAIT_0) { @@ -261,7 +267,9 @@ ExInterlockedInsertHeadList(&ThreadListHead, &Container->ListEntry, &ThreadListLock); + ACQUIRE_SERIAL_MUTEX(); Container->ThreadFunction(Container->ThreadContext); + RELEASE_SERIAL_MUTEX(); KeAcquireSpinLock(&ThreadListLock, &OldIrql); RemoveEntryList(&Container->ListEntry); @@ -311,6 +319,9 @@ KeQuerySystemTime(&StartTime); KeInitializeEvent(&TerminationEvent, NotificationEvent, FALSE); + KeInitializeMutex(&MTSerialMutex, 0); + + ACQUIRE_SERIAL_MUTEX(); } void @@ -329,13 +340,15 @@ if (Container->ThreadFunction) { + RELEASE_SERIAL_MUTEX(); KeWaitForSingleObject(Container->Handle, Executive, KernelMode, FALSE, NULL); + ACQUIRE_SERIAL_MUTEX(); ZwClose(Container->Handle); } } -} +}
8 years, 4 months
1
0
0
0
[cwittich] 72103: [BROWSEUI] set min width for addressband to 100. patch by Katayama Hirofumi MZ CORE-11766
by cwittich@svn.reactos.org
Author: cwittich Date: Wed Aug 3 17:59:53 2016 New Revision: 72103 URL:
http://svn.reactos.org/svn/reactos?rev=72103&view=rev
Log: [BROWSEUI] set min width for addressband to 100. patch by Katayama Hirofumi MZ CORE-11766 Modified: trunk/reactos/dll/win32/browseui/addressband.cpp Modified: trunk/reactos/dll/win32/browseui/addressband.cpp URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/browseui/address…
============================================================================== --- trunk/reactos/dll/win32/browseui/addressband.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/browseui/addressband.cpp [iso-8859-1] Wed Aug 3 17:59:53 2016 @@ -66,7 +66,7 @@ { if (pdbi->dwMask & DBIM_MINSIZE) { - pdbi->ptMinSize.x = 400; + pdbi->ptMinSize.x = 100; pdbi->ptMinSize.y = 22; } if (pdbi->dwMask & DBIM_MAXSIZE) @@ -81,7 +81,7 @@ } if (pdbi->dwMask & DBIM_ACTUAL) { - pdbi->ptActual.x = 400; + pdbi->ptActual.x = 100; pdbi->ptActual.y = 22; } if (pdbi->dwMask & DBIM_TITLE)
8 years, 4 months
1
0
0
0
[jimtabor] 72102: [NtUser] - Fix regression from r66350. See CORE-11324 for more details.
by jimtabor@svn.reactos.org
Author: jimtabor Date: Wed Aug 3 17:41:22 2016 New Revision: 72102 URL:
http://svn.reactos.org/svn/reactos?rev=72102&view=rev
Log: [NtUser] - Fix regression from r66350. See CORE-11324 for more details. Modified: trunk/reactos/win32ss/user/ntuser/winpos.c Modified: trunk/reactos/win32ss/user/ntuser/winpos.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/winpos…
============================================================================== --- trunk/reactos/win32ss/user/ntuser/winpos.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/winpos.c [iso-8859-1] Wed Aug 3 17:41:22 2016 @@ -1759,7 +1759,7 @@ RECTL CopyRect; PWND Ancestor; BOOL bPointerInWindow; - PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); + //PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); ASSERT_REFS_CO(Window); @@ -2126,6 +2126,7 @@ { co_IntSendMessageNoWait(WinPos.hwnd, WM_CHILDACTIVATE, 0, 0); } +#if 0 ////// Break see CORE-11324 /* Do not allow setting if already active. Fix A : wine msg test_SetParent:WmSetParentSeq_2:25 msg! Recursion broke the tests. @@ -2142,6 +2143,16 @@ co_IntSetForegroundWindow(Window); } } +#else ////// + else + { + //ERR("SetWindowPos Set FG Window!\n"); + if (Window->state & WNDS_BEINGACTIVATED) // Inside SAW? + co_IntSetActiveWindow(Window, FALSE, TRUE, FALSE); // Fixes Api AttachThreadInput tests. + else + co_IntSetForegroundWindow(Window); // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow. + } +#endif } // Fix wine msg test_SetFocus, prevents sending WM_WINDOWPOSCHANGED. @@ -2449,7 +2460,8 @@ ((Cmd == SW_SHOW) || (Cmd == SW_NORMAL))) { ERR("WinPosShowWindow Set active\n"); - UserSetActiveWindow(Wnd); + //UserSetActiveWindow(Wnd); + co_IntSetForegroundWindow(Wnd); // HACK Swp |= SWP_NOACTIVATE | SWP_NOZORDER; } #endif
8 years, 4 months
1
0
0
0
[tfaber] 72101: [NTOS:SE] - Remove unnecessary null checks & fix up cleanup in SepCreateToken and SepDuplicateToken. Based on a patch by Víctor Martínez Calvo CORE-11768 #resolve
by tfaber@svn.reactos.org
Author: tfaber Date: Wed Aug 3 17:10:59 2016 New Revision: 72101 URL:
http://svn.reactos.org/svn/reactos?rev=72101&view=rev
Log: [NTOS:SE] - Remove unnecessary null checks & fix up cleanup in SepCreateToken and SepDuplicateToken. Based on a patch by Víctor Martínez Calvo CORE-11768 #resolve Modified: trunk/reactos/ntoskrnl/se/token.c Modified: trunk/reactos/ntoskrnl/se/token.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/token.c?rev=72…
============================================================================== --- trunk/reactos/ntoskrnl/se/token.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/se/token.c [iso-8859-1] Wed Aug 3 17:10:59 2016 @@ -373,7 +373,7 @@ ULONG uLength; ULONG i; PVOID EndMem; - PTOKEN AccessToken = NULL; + PTOKEN AccessToken; NTSTATUS Status; PAGED_CODE(); @@ -400,9 +400,12 @@ AccessToken->TokenLock = &SepTokenLock; + /* Copy and reference the logon session */ + RtlCopyLuid(&AccessToken->AuthenticationId, &Token->AuthenticationId); + SepRmReferenceLogonSession(&AccessToken->AuthenticationId); + AccessToken->TokenType = TokenType; AccessToken->ImpersonationLevel = Level; - RtlCopyLuid(&AccessToken->AuthenticationId, &Token->AuthenticationId); RtlCopyLuid(&AccessToken->ModifiedId, &Token->ModifiedId); AccessToken->TokenSource.SourceIdentifier.LowPart = Token->TokenSource.SourceIdentifier.LowPart; @@ -483,25 +486,11 @@ *NewAccessToken = AccessToken; - /* Reference the logon session */ - SepRmReferenceLogonSession(&AccessToken->AuthenticationId); - done: if (!NT_SUCCESS(Status)) { - if (AccessToken) - { - if (AccessToken->UserAndGroups) - ExFreePoolWithTag(AccessToken->UserAndGroups, TAG_TOKEN_USERS); - - if (AccessToken->Privileges) - ExFreePoolWithTag(AccessToken->Privileges, TAG_TOKEN_PRIVILAGES); - - if (AccessToken->DefaultDacl) - ExFreePoolWithTag(AccessToken->DefaultDacl, TAG_TOKEN_ACL); - - ObDereferenceObject(AccessToken); - } + /* Dereference the token, the delete procedure will clean up */ + ObDereferenceObject(AccessToken); } return Status; @@ -759,8 +748,11 @@ TokenSource->SourceName, sizeof(TokenSource->SourceName)); + /* Copy and reference the logon session */ + RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId); + SepRmReferenceLogonSession(&AccessToken->AuthenticationId); + RtlCopyLuid(&AccessToken->TokenId, &TokenId); - RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId); AccessToken->ExpirationTime = *ExpirationTime; RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId); @@ -899,17 +891,11 @@ *TokenHandle = (HANDLE)AccessToken; } - /* Reference the logon session */ - SepRmReferenceLogonSession(AuthenticationId); - done: if (!NT_SUCCESS(Status)) { - if (AccessToken) - { - /* Dereference the token, the delete procedure will clean up */ - ObDereferenceObject(AccessToken); - } + /* Dereference the token, the delete procedure will clean up */ + ObDereferenceObject(AccessToken); } return Status; @@ -1091,7 +1077,7 @@ DPRINT1("SeQueryInformationToken(%d) invalid information class\n", TokenInformationClass); return STATUS_INVALID_INFO_CLASS; } - + switch (TokenInformationClass) { case TokenImpersonationLevel:
8 years, 4 months
1
0
0
0
[gadamopoulos] 72100: Fix gcc build
by gadamopoulos@svn.reactos.org
Author: gadamopoulos Date: Wed Aug 3 15:55:58 2016 New Revision: 72100 URL:
http://svn.reactos.org/svn/reactos?rev=72100&view=rev
Log: Fix gcc build Modified: trunk/reactos/dll/win32/shell32/shelldesktop/CDesktopBrowser.cpp Modified: trunk/reactos/dll/win32/shell32/shelldesktop/CDesktopBrowser.cpp URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/shelldes…
============================================================================== --- trunk/reactos/dll/win32/shell32/shelldesktop/CDesktopBrowser.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/shelldesktop/CDesktopBrowser.cpp [iso-8859-1] Wed Aug 3 15:55:58 2016 @@ -96,8 +96,8 @@ }; CDesktopBrowser::CDesktopBrowser(): - m_hWndShellView(NULL), - m_hAccel(NULL) + m_hAccel(NULL), + m_hWndShellView(NULL) { }
8 years, 4 months
1
0
0
0
[gadamopoulos] 72099: [SHELL32] - CDesktopBrowser: Convert to an ATL CWindow class, remove unused fields and cleanup.
by gadamopoulos@svn.reactos.org
Author: gadamopoulos Date: Wed Aug 3 15:52:27 2016 New Revision: 72099 URL:
http://svn.reactos.org/svn/reactos?rev=72099&view=rev
Log: [SHELL32] - CDesktopBrowser: Convert to an ATL CWindow class, remove unused fields and cleanup. Modified: trunk/reactos/dll/win32/shell32/shelldesktop/CDesktopBrowser.cpp Modified: trunk/reactos/dll/win32/shell32/shelldesktop/CDesktopBrowser.cpp URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/shelldes…
============================================================================== --- trunk/reactos/dll/win32/shell32/shelldesktop/CDesktopBrowser.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/shelldesktop/CDesktopBrowser.cpp [iso-8859-1] Wed Aug 3 15:52:27 2016 @@ -22,42 +22,27 @@ WINE_DEFAULT_DEBUG_CHANNEL(desktop); -#define SHDESK_TAG 'KSED' - static const WCHAR szProgmanClassName[] = L"Progman"; static const WCHAR szProgmanWindowName[] = L"Program Manager"; class CDesktopBrowser : + public CWindowImpl<CDesktopBrowser, CWindow, CFrameWinTraits>, public CComObjectRootEx<CComMultiThreadModelNoCS>, public IShellBrowser, - public ICommDlgBrowser, public IServiceProvider { -public: - DWORD Tag; +private: HACCEL m_hAccel; -private: - HWND hWnd; - HWND hWndShellView; - HWND hWndDesktopListView; // FIXME: Unused - CComPtr<IShellDesktopTray> ShellDesk; - CComPtr<IShellView> DesktopView; - CComPtr<IShellBrowser> DefaultShellBrowser; - LPITEMIDLIST pidlDesktopDirectory; - LPITEMIDLIST pidlDesktop; + HWND m_hWndShellView; + CComPtr<IShellDesktopTray> m_Tray; + CComPtr<IShellView> m_ShellView; LRESULT _NotifyTray(UINT uMsg, WPARAM wParam, LPARAM lParam); public: CDesktopBrowser(); ~CDesktopBrowser(); - HRESULT Initialize(HWND hWndx, IShellDesktopTray *ShellDeskx); - HWND FindDesktopListView(); - BOOL CreateDeskWnd(); - HWND DesktopGetWindowControl(IN UINT id); - LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam); - static LRESULT CALLBACK ProgmanWindowProc(IN HWND hwnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam); - BOOL MessageLoop(); + HRESULT Initialize(IShellDesktopTray *ShellDeskx); // *** IOleWindow methods *** virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd); @@ -78,128 +63,96 @@ virtual HRESULT STDMETHODCALLTYPE OnViewWindowActive(struct IShellView *ppshv); virtual HRESULT STDMETHODCALLTYPE SetToolbarItems(LPTBBUTTON lpButtons, UINT nButtons, UINT uFlags); - // *** ICommDlgBrowser methods *** - virtual HRESULT STDMETHODCALLTYPE OnDefaultCommand (struct IShellView *ppshv); - virtual HRESULT STDMETHODCALLTYPE OnStateChange (struct IShellView *ppshv, ULONG uChange); - virtual HRESULT STDMETHODCALLTYPE IncludeObject (struct IShellView *ppshv, LPCITEMIDLIST pidl); - // *** IServiceProvider methods *** virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject); + + // message handlers + LRESULT OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnOpenNewWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + +DECLARE_WND_CLASS_EX(szProgmanClassName, CS_DBLCLKS, COLOR_DESKTOP) + +BEGIN_MSG_MAP(CBaseBar) + MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd) + MESSAGE_HANDLER(WM_SIZE, OnSize) + MESSAGE_HANDLER(WM_SYSCOLORCHANGE, OnSettingChange) + MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) + MESSAGE_HANDLER(WM_CLOSE, OnClose) + MESSAGE_HANDLER(WM_EXPLORER_OPEN_NEW_WINDOW, OnOpenNewWindow) + MESSAGE_HANDLER(WM_COMMAND, OnCommand) + MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) +END_MSG_MAP() BEGIN_COM_MAP(CDesktopBrowser) COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow) COM_INTERFACE_ENTRY_IID(IID_IShellBrowser, IShellBrowser) - COM_INTERFACE_ENTRY_IID(IID_ICommDlgBrowser, ICommDlgBrowser) COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider) END_COM_MAP() }; -CDesktopBrowser::CDesktopBrowser() -{ - Tag = SHDESK_TAG; - hWnd = NULL; - hWndShellView = NULL; - hWndDesktopListView = NULL; - DefaultShellBrowser = NULL; - pidlDesktopDirectory = NULL; - pidlDesktop = NULL; +CDesktopBrowser::CDesktopBrowser(): + m_hWndShellView(NULL), + m_hAccel(NULL) +{ } CDesktopBrowser::~CDesktopBrowser() { - if (DesktopView.p != NULL) - { - if (hWndShellView != NULL) - DesktopView->DestroyViewWindow(); - - hWndShellView = NULL; - hWndDesktopListView = NULL; - } - - if (pidlDesktopDirectory != NULL) - { - ILFree(pidlDesktopDirectory); - pidlDesktopDirectory = NULL; - } - - if (pidlDesktop != NULL) - { - ILFree(pidlDesktop); - pidlDesktop = NULL; - } -} - -HRESULT CDesktopBrowser::Initialize(HWND hWndx, IShellDesktopTray *ShellDeskx) -{ - CComPtr<IShellFolder> psfDesktopFolder; - CSFV csfv; + if (m_ShellView.p != NULL && m_hWndShellView != NULL) + { + m_ShellView->DestroyViewWindow(); + } +} + +HRESULT CDesktopBrowser::Initialize(IShellDesktopTray *ShellDesk) +{ + CComPtr<IShellFolder> psfDesktop; HRESULT hRet; - - hWnd = hWndx; - ShellDesk = ShellDeskx; - ShellDesk->AddRef(); - - pidlDesktopDirectory = SHCloneSpecialIDList(hWnd, CSIDL_DESKTOPDIRECTORY, FALSE); - hRet = SHGetSpecialFolderLocation(hWnd, CSIDL_DESKTOP, &pidlDesktop); - if (FAILED(hRet)) + hRet = SHGetDesktopFolder(&psfDesktop); + if (FAILED_UNEXPECTEDLY(hRet)) return hRet; - hRet = SHGetDesktopFolder(&psfDesktopFolder); - if (FAILED(hRet)) + /* Calculate the size and pos of the window */ + RECT rect; + if (!GetSystemMetrics(SM_CXVIRTUALSCREEN) || GetSystemMetrics(SM_CYVIRTUALSCREEN)) + { + SetRect(&rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); + } + else + { + SetRect(&rect, + GetSystemMetrics(SM_XVIRTUALSCREEN), + GetSystemMetrics(SM_YVIRTUALSCREEN), + GetSystemMetrics(SM_XVIRTUALSCREEN) + GetSystemMetrics(SM_CXVIRTUALSCREEN), + GetSystemMetrics(SM_YVIRTUALSCREEN) + GetSystemMetrics(SM_CYVIRTUALSCREEN)); + } + + + m_Tray = ShellDesk; + + Create(NULL, &rect, szProgmanWindowName, WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_TOOLWINDOW); + if (!m_hWnd) + return E_FAIL; + + CSFV csfv = {sizeof(CSFV), psfDesktop}; + hRet = SHCreateShellFolderViewEx(&csfv, &m_ShellView); + if (FAILED_UNEXPECTEDLY(hRet)) return hRet; - ZeroMemory(&csfv, sizeof(csfv)); - csfv.cbSize = sizeof(csfv); - csfv.pshf = psfDesktopFolder; - csfv.psvOuter = NULL; - - hRet = SHCreateShellFolderViewEx(&csfv, &DesktopView); - - return hRet; -} - -static CDesktopBrowser *SHDESK_Create(HWND hWnd, LPCREATESTRUCT lpCreateStruct) -{ - CComPtr<IShellDesktopTray> ShellDesk; - CComObject<CDesktopBrowser> *pThis; - HRESULT hRet; - - ShellDesk = (IShellDesktopTray *)lpCreateStruct->lpCreateParams; - if (ShellDesk == NULL) - { - WARN("No IShellDesk interface provided!"); - return NULL; - } - - pThis = new CComObject<CDesktopBrowser>; - - pThis->AddRef(); - - hRet = pThis->Initialize(hWnd, ShellDesk); - if (FAILED(hRet)) - { - pThis->Release(); - delete pThis; - return NULL; - } - - return pThis; -} - -HWND CDesktopBrowser::FindDesktopListView() -{ - return FindWindowExW(hWndShellView, NULL, WC_LISTVIEW, NULL); -} - -BOOL CDesktopBrowser::CreateDeskWnd() -{ + m_Tray->RegisterDesktopWindow(m_hWnd); + if (FAILED_UNEXPECTEDLY(hRet)) + return hRet; + FOLDERSETTINGS fs; RECT rcWorkArea; - HRESULT hRet; // FIXME: Add support for multi-monitor? - SystemParametersInfoW(SPI_GETWORKAREA, - 0, &rcWorkArea, 0); + SystemParametersInfoW(SPI_GETWORKAREA, 0, &rcWorkArea, 0); // TODO: Call GetClientRect for the tray window and make small computation // to be sure the tray window rect is removed from the work area! @@ -208,38 +161,39 @@ HWND hWndTray; /* Get client rect of the taskbar */ - hRet = ShellDesk->GetTrayWindow(&hWndTray); + hRet = m_Tray->GetTrayWindow(&hWndTray); if (SUCCEEDED(hRet)) GetClientRect(hWndTray, &rcTray); #endif fs.ViewMode = FVM_ICON; fs.fFlags = FWF_DESKTOP | FWF_NOCLIENTEDGE | FWF_NOSCROLL | FWF_TRANSPARENT; - hRet = DesktopView->CreateViewWindow(NULL, &fs, (IShellBrowser *)this, &rcWorkArea, &hWndShellView); - if (!SUCCEEDED(hRet)) - return FALSE; - - SetShellWindowEx(hWnd, FindDesktopListView()); + hRet = m_ShellView->CreateViewWindow(NULL, &fs, (IShellBrowser *)this, &rcWorkArea, &m_hWndShellView); + if (FAILED_UNEXPECTEDLY(hRet)) + return hRet; + + HWND hwndListView = FindWindowExW(m_hWndShellView, NULL, WC_LISTVIEW, NULL); + SetShellWindowEx(m_hWnd, hwndListView); + + m_hAccel = LoadAcceleratorsW(shell32_hInstance, MAKEINTRESOURCEW(IDA_DESKBROWSER)); #if 1 /* A Windows8+ specific hack */ - ::ShowWindow(hWndShellView, SW_SHOW); - ::ShowWindow(FindDesktopListView(), SW_SHOW); + ::ShowWindow(m_hWndShellView, SW_SHOW); + ::ShowWindow(hwndListView, SW_SHOW); #endif - - return TRUE; -} - -HRESULT STDMETHODCALLTYPE CDesktopBrowser::GetWindow(HWND *phwnd) -{ - if (hWnd != NULL) - { - *phwnd = hWnd; - return S_OK; - } - - *phwnd = NULL; - return E_UNEXPECTED; + ShowWindow(SW_SHOW); + UpdateWindow(); + + return hRet; +} + +HRESULT STDMETHODCALLTYPE CDesktopBrowser::GetWindow(HWND *lphwnd) +{ + if (lphwnd == NULL) + return E_POINTER; + *lphwnd = m_hWnd; + return S_OK; } HRESULT STDMETHODCALLTYPE CDesktopBrowser::ContextSensitiveHelp(BOOL fEnterMode) @@ -274,7 +228,7 @@ HRESULT STDMETHODCALLTYPE CDesktopBrowser::TranslateAcceleratorSB(LPMSG lpmsg, WORD wID) { - if (!::TranslateAcceleratorW(hWnd, m_hAccel, lpmsg)) + if (!::TranslateAcceleratorW(m_hWnd, m_hAccel, lpmsg)) return S_FALSE; return S_OK; } @@ -294,62 +248,27 @@ return E_NOTIMPL; } -HWND CDesktopBrowser::DesktopGetWindowControl(IN UINT id) -{ - switch (id) - { - case FCW_TOOLBAR: - case FCW_STATUS: - case FCW_TREE: - case FCW_PROGRESS: - return NULL; - - default: - return NULL; - } - -} - HRESULT STDMETHODCALLTYPE CDesktopBrowser::GetControlWindow(UINT id, HWND *lphwnd) { - HWND hWnd; - - hWnd = DesktopGetWindowControl(id); - if (hWnd != NULL) - { - *lphwnd = hWnd; - return S_OK; - } - - *lphwnd = NULL; + if (lphwnd == NULL) + return E_POINTER; return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CDesktopBrowser::SendControlMsg(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pret) { - HWND hWnd; - if (pret == NULL) return E_POINTER; - - hWnd = DesktopGetWindowControl(id); - if (hWnd != NULL) - { - *pret = SendMessageW(hWnd, - uMsg, - wParam, - lParam); - return S_OK; - } - return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CDesktopBrowser::QueryActiveShellView(IShellView **ppshv) { - *ppshv = DesktopView; - if (DesktopView != NULL) - DesktopView->AddRef(); + if (ppshv == NULL) + return E_POINTER; + *ppshv = m_ShellView; + if (m_ShellView != NULL) + m_ShellView->AddRef(); return S_OK; } @@ -362,21 +281,6 @@ HRESULT STDMETHODCALLTYPE CDesktopBrowser::SetToolbarItems(LPTBBUTTON lpButtons, UINT nButtons, UINT uFlags) { return E_NOTIMPL; -} - -HRESULT STDMETHODCALLTYPE CDesktopBrowser::OnDefaultCommand(IShellView *ppshv) -{ - return E_NOTIMPL; -} - -HRESULT STDMETHODCALLTYPE CDesktopBrowser::OnStateChange(IShellView *ppshv, ULONG uChange) -{ - return S_OK; -} - -HRESULT STDMETHODCALLTYPE CDesktopBrowser::IncludeObject(IShellView *ppshv, LPCITEMIDLIST pidl) -{ - return S_OK; } HRESULT STDMETHODCALLTYPE CDesktopBrowser::QueryService(REFGUID guidService, REFIID riid, PVOID *ppv) @@ -385,40 +289,19 @@ return QueryInterface(riid, ppv); } -BOOL CDesktopBrowser::MessageLoop() -{ - MSG Msg; - BOOL bRet; - - while ((bRet = GetMessageW(&Msg, NULL, 0, 0)) != 0) - { - if (bRet != -1) - { - if (DesktopView->TranslateAcceleratorW(&Msg) != S_OK) - { - TranslateMessage(&Msg); - DispatchMessage(&Msg); - } - } - } - - return TRUE; -} - LRESULT CDesktopBrowser::_NotifyTray(UINT uMsg, WPARAM wParam, LPARAM lParam) { HWND hWndTray; HRESULT hRet; - hRet = ShellDesk->GetTrayWindow(&hWndTray); - + hRet = m_Tray->GetTrayWindow(&hWndTray); if (SUCCEEDED(hRet)) - PostMessageW(hWndTray, uMsg, wParam, lParam); - - return 0; -} - -LRESULT CDesktopBrowser::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam) + ::PostMessageW(hWndTray, uMsg, wParam, lParam); + + return 0; +} + +LRESULT CDesktopBrowser::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { switch (LOWORD(wParam)) { @@ -439,217 +322,102 @@ return 0; } -LRESULT CALLBACK CDesktopBrowser::ProgmanWindowProc(IN HWND hwnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam) -{ - CDesktopBrowser *pThis = NULL; - LRESULT Ret = FALSE; - - if (uMsg != WM_NCCREATE) - { - pThis = reinterpret_cast<CDesktopBrowser *>(GetWindowLongPtrW(hwnd, 0)); - if (pThis == NULL) - goto DefMsgHandler; - } - - if (pThis != NULL || uMsg == WM_NCCREATE) - { - switch (uMsg) - { - case WM_ERASEBKGND: - return (LRESULT)PaintDesktop((HDC)wParam); - - case WM_GETISHELLBROWSER: - Ret = (LRESULT)((IShellBrowser *)pThis); - break; - - case WM_SIZE: - { - if (wParam == SIZE_MINIMIZED) - { - /* Hey, we're the desktop!!! */ - ShowWindow(hwnd, SW_RESTORE); - } - else - { - RECT rcDesktop; - - rcDesktop.left = GetSystemMetrics(SM_XVIRTUALSCREEN); - rcDesktop.top = GetSystemMetrics(SM_YVIRTUALSCREEN); - rcDesktop.right = GetSystemMetrics(SM_CXVIRTUALSCREEN); - rcDesktop.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN); - - /* FIXME: Update work area */ - DBG_UNREFERENCED_LOCAL_VARIABLE(rcDesktop); - } - break; - } - - case WM_SYSCOLORCHANGE: - case WM_SETTINGCHANGE: - { - if (pThis->hWndShellView != NULL) - { - /* Forward the message */ - SendMessageW(pThis->hWndShellView, - uMsg, - wParam, - lParam); - } - - if (uMsg == WM_SETTINGCHANGE && wParam == SPI_SETWORKAREA && - pThis->hWndShellView != NULL) - { - RECT rcWorkArea; - - // FIXME: Add support for multi-monitor! - // FIXME: Maybe merge with the code that retrieves the - // work area in CDesktopBrowser::CreateDeskWnd ? - SystemParametersInfoW(SPI_GETWORKAREA, - 0, &rcWorkArea, 0); - - SetWindowPos(pThis->hWndShellView, NULL, - rcWorkArea.left, rcWorkArea.top, - rcWorkArea.right - rcWorkArea.left, - rcWorkArea.bottom - rcWorkArea.top, - SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER); - } - break; - } - - case WM_CREATE: - { - pThis->ShellDesk->RegisterDesktopWindow(pThis->hWnd); - - if (!pThis->CreateDeskWnd()) - WARN("Could not create the desktop view control!\n"); - - pThis->m_hAccel = LoadAcceleratorsW(shell32_hInstance, MAKEINTRESOURCEW(IDA_DESKBROWSER)); - - break; - } - - case WM_NCCREATE: - { - LPCREATESTRUCT CreateStruct = (LPCREATESTRUCT)lParam; - - // FIXME: This is a "hack" to enforce the window title - // to be set to what it should be *on Windows* only. - // I don't understand why it is reset to NULL whereas - // the creation of the progman window proper is done in - // the standard way... (05/06/2016, hbelusca). - // - ::SetWindowTextW(hwnd, CreateStruct->lpszName); - - pThis = SHDESK_Create(hwnd, CreateStruct); - if (pThis == NULL) - { - WARN("Failed to create desktop structure\n"); - break; - } - - SetWindowLongPtrW(hwnd, 0, (LONG_PTR)pThis); - Ret = TRUE; - break; - } - - case WM_NCDESTROY: - { - pThis->Release(); - break; - } - - case WM_CLOSE: - return pThis->_NotifyTray(TWM_DOEXITWINDOWS, 0, 0); - - case WM_EXPLORER_OPEN_NEW_WINDOW: - TRACE("Proxy Desktop message 1035 received.\n"); - SHOnCWMCommandLine((HANDLE)lParam); - break; - - case WM_COMMAND: - return pThis->OnCommand(uMsg, wParam, lParam); - - case WM_SETFOCUS: - SetFocus(pThis->hWndShellView); - break; - - default: -DefMsgHandler: - Ret = DefWindowProcW(hwnd, uMsg, wParam, lParam); - break; - } - } - - return Ret; -} - -static BOOL -RegisterProgmanWindowClass(VOID) -{ - WNDCLASSW wcProgman; - - wcProgman.style = CS_DBLCLKS; - wcProgman.lpfnWndProc = CDesktopBrowser::ProgmanWindowProc; - wcProgman.cbClsExtra = 0; - wcProgman.cbWndExtra = sizeof(CDesktopBrowser *); - wcProgman.hInstance = shell32_hInstance; - wcProgman.hIcon = NULL; - wcProgman.hCursor = LoadCursorW(NULL, IDC_ARROW); - wcProgman.hbrBackground = (HBRUSH)(COLOR_DESKTOP + 1); - wcProgman.lpszMenuName = NULL; - wcProgman.lpszClassName = szProgmanClassName; - - return RegisterClassW(&wcProgman) != 0; -} - + +LRESULT CDesktopBrowser::OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) +{ + return (LRESULT)PaintDesktop((HDC)wParam); +} + +LRESULT CDesktopBrowser::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) +{ + if (wParam == SIZE_MINIMIZED) + { + /* Hey, we're the desktop!!! */ + ::ShowWindow(m_hWnd, SW_RESTORE); + } + else + { + RECT rcDesktop; + rcDesktop.left = GetSystemMetrics(SM_XVIRTUALSCREEN); + rcDesktop.top = GetSystemMetrics(SM_YVIRTUALSCREEN); + rcDesktop.right = GetSystemMetrics(SM_CXVIRTUALSCREEN); + rcDesktop.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN); + + /* FIXME: Update work area */ + DBG_UNREFERENCED_LOCAL_VARIABLE(rcDesktop); + } + + return 0; +} + +LRESULT CDesktopBrowser::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) +{ + if (m_hWndShellView) + { + /* Forward the message */ + SendMessageW(m_hWndShellView, uMsg, wParam, lParam); + } + + if (uMsg == WM_SETTINGCHANGE && wParam == SPI_SETWORKAREA && + m_hWndShellView != NULL) + { + RECT rcWorkArea; + + // FIXME: Add support for multi-monitor! + // FIXME: Maybe merge with the code that retrieves the + // work area in CDesktopBrowser::CreateDeskWnd ? + SystemParametersInfoW(SPI_GETWORKAREA, 0, &rcWorkArea, 0); + + ::SetWindowPos(m_hWndShellView, NULL, + rcWorkArea.left, rcWorkArea.top, + rcWorkArea.right - rcWorkArea.left, + rcWorkArea.bottom - rcWorkArea.top, + SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER); + } + return 0; +} + +LRESULT CDesktopBrowser::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) +{ + return _NotifyTray(TWM_DOEXITWINDOWS, 0, 0); +} + +LRESULT CDesktopBrowser::OnOpenNewWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) +{ + TRACE("Proxy Desktop message 1035 received.\n"); + SHOnCWMCommandLine((HANDLE)lParam); + return 0; +} + +LRESULT CDesktopBrowser::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) +{ + ::SetFocus(m_hWndShellView); + return 0; +} + +HRESULT CDesktopBrowser_CreateInstance(IShellDesktopTray *Tray, REFIID riid, void **ppv) +{ + return ShellObjectCreatorInit<CDesktopBrowser, IShellDesktopTray*>(Tray, riid, ppv); +} /************************************************************************* * SHCreateDesktop [SHELL32.200] * */ -HANDLE WINAPI SHCreateDesktop(IShellDesktopTray *ShellDesk) -{ - HWND hWndDesk; - int x, y, cx, cy; - - if (ShellDesk == NULL) +HANDLE WINAPI SHCreateDesktop(IShellDesktopTray *Tray) +{ + if (Tray == NULL) { SetLastError(ERROR_INVALID_PARAMETER); return NULL; } - if (RegisterProgmanWindowClass() == 0) - { - WARN("Failed to register the Progman window class!\n"); + CComPtr<IShellBrowser> Browser; + HRESULT hr = CDesktopBrowser_CreateInstance(Tray, IID_PPV_ARG(IShellBrowser, &Browser)); + if (FAILED_UNEXPECTEDLY(hr)) return NULL; - } - - x = GetSystemMetrics(SM_XVIRTUALSCREEN); - y = GetSystemMetrics(SM_YVIRTUALSCREEN); - cx = GetSystemMetrics(SM_CXVIRTUALSCREEN); - cy = GetSystemMetrics(SM_CYVIRTUALSCREEN); - - if (!cx || !cy) - { - x = y = 0; - cx = GetSystemMetrics(SM_CXSCREEN); - cy = GetSystemMetrics(SM_CYSCREEN); - } - - hWndDesk = ::CreateWindowExW(WS_EX_TOOLWINDOW, szProgmanClassName, szProgmanWindowName, - WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, - x, y, cx, cy, - NULL, NULL, shell32_hInstance, (LPVOID)ShellDesk); - - if (hWndDesk != NULL) - { - ::ShowWindow(hWndDesk, SW_SHOW); - ::UpdateWindow(hWndDesk); - - return (HANDLE)GetWindowLongPtrW(hWndDesk, 0); - } - - return NULL; + + return static_cast<HANDLE>(Browser.Detach()); } /************************************************************************* @@ -658,13 +426,34 @@ */ BOOL WINAPI SHDesktopMessageLoop(HANDLE hDesktop) { - CDesktopBrowser *Desk = static_cast<CDesktopBrowser *>(hDesktop); - - if (Desk == NULL || Desk->Tag != SHDESK_TAG) + if (hDesktop == NULL) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - return Desk->MessageLoop(); -} + MSG Msg; + BOOL bRet; + + CComPtr<IShellBrowser> browser; + CComPtr<IShellView> shellView; + + browser.Attach(static_cast<IShellBrowser*>(hDesktop)); + HRESULT hr = browser->QueryActiveShellView(&shellView); + if (FAILED_UNEXPECTEDLY(hr)) + return FALSE; + + while ((bRet = GetMessageW(&Msg, NULL, 0, 0)) != 0) + { + if (bRet != -1) + { + if (shellView->TranslateAcceleratorW(&Msg) != S_OK) + { + TranslateMessage(&Msg); + DispatchMessage(&Msg); + } + } + } + + return TRUE; +}
8 years, 4 months
1
0
0
0
← Newer
1
...
40
41
42
43
44
45
46
47
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Results per page:
10
25
50
100
200