Windows Filtering Platform And Windows Filtering Platform And Winsock Kernel: Winsock Kernel: Next-Generation Kernel Next-Generation Kernel Networking APIsNetworking APIs
Madhurima PawarMadhurima PawarProgram ManagerProgram ManagerWindows NetworkingWindows Networkingmpawar @ microsoft.commpawar @ microsoft.comMicrosoft CorporationMicrosoft Corporation
Eric Stenson
Development LeadWindows Networkingericsten @ microsoft.comMicrosoft Corporation
Session OutlineSession Outline
Windows Filtering Platform (WFP)Windows Filtering Platform (WFP)WFP IntroductionWFP Introduction
WFP BasicsWFP Basics
WFP ArchitectureWFP Architecture
WFP ConfigurationWFP Configuration
WFP Callout DriversWFP Callout Drivers
Case Study: Data logging callout driverCase Study: Data logging callout driver
Winsock Kernel (WSK)Winsock Kernel (WSK)Why WSK?Why WSK?
TDI ShortcomingsTDI Shortcomings
WSK BenefitsWSK Benefits
WSK Versus TDI Scenario ComparisonWSK Versus TDI Scenario Comparison
QuestionsQuestions
Session GoalsSession Goals
Attendees should leave this session Attendees should leave this session with the followingwith the following
An introduction to Windows Firewall An introduction to Windows Firewall Platform (WFP)Platform (WFP)
An introduction to Winsock Kernel (WSK)An introduction to Winsock Kernel (WSK)
Knowledge of where to find resources for Knowledge of where to find resources for WFP and WSKWFP and WSK
Windows Filtering Platform Windows Filtering Platform (WFP)(WFP)
WFP IntroductionWFP Introduction
What is WFP?What is WFP?Windows Filtering Platform exposes a set of Application Windows Filtering Platform exposes a set of Application Programming Interfaces (APIs) to permit, block, modify and/or Programming Interfaces (APIs) to permit, block, modify and/or secure inbound and outbound trafficsecure inbound and outbound traffic
APIs are categorized asAPIs are categorized asManagement APIsManagement APIs
Filter management, provider management, callout managementFilter management, provider management, callout management
IKE (Keying Module) Management APIsIKE (Keying Module) Management APIs
Internet Protocol Security (IPsec) Management APIsInternet Protocol Security (IPsec) Management APIs
APIs are for user mode as well as kernel-mode componentsAPIs are for user mode as well as kernel-mode components
APIs can be used forAPIs can be used forFirewallFirewall
AntivirusAntivirus
Parental controlParental control
DiagnosticsDiagnostics
WFP BasicsWFP Basics
Why WFP?Why WFP?Easier and cleaner interface to the network stackEasier and cleaner interface to the network stack
Filter hooks and firewall hooks are no longer supportedFilter hooks and firewall hooks are no longer supported
Reduces and/or eliminates the use of Network Driver Interface Reduces and/or eliminates the use of Network Driver Interface Specification (NDIS) or LSPSpecification (NDIS) or LSP
Callout drivers allow content inspection and data modificationCallout drivers allow content inspection and data modification
Provides rich set of filters in user and kernel modeProvides rich set of filters in user and kernel modeAllows multiple providers to co-exist on Allows multiple providers to co-exist on Windows Codename Windows Codename LonghornLonghornSupports both IPv4 and IPv6Supports both IPv4 and IPv6Allows integration of IPsec and firewall policiesAllows integration of IPsec and firewall policiesImproves diagnostics and traceabilityImproves diagnostics and traceabilityReduces firewall and anti-virus crashesReduces firewall and anti-virus crashes
12% of all OS crashes12% of all OS crashes
WFP ArchitectureWFP Architecture
Base Filtering Engine
Filtering Engine
TDI, WSK
NAT
Firewall or other filter applicationsLH Firewall
WFP APIs
ALE
Stream Layer
TCP, UDPTransport Layer
NetworkLayer
NDIS Layer
ForwardingLayer
Pac
ketp
roce
ssin
g p
ath
Pac
ketp
roce
ssin
g p
ath
Cal
lou
t A
PIs
IDS callout
Parentalcontrol
Anti-virus Callo
ut m
od
ules
Callo
ut m
od
ules
useruser
kernelkernel
Provided by:
Microsoft
ISV
OEMOEM
IHV
WFP ConfigurationWFP Configuration
WFP can be configured usingWFP can be configured usingUser mode components (applications and services) User mode components (applications and services) for filtering operationsfor filtering operations
Kernel mode components (callout drivers) for deep Kernel mode components (callout drivers) for deep packet inspection and modificationpacket inspection and modification
User mode components can configure WFP by User mode components can configure WFP by plumbing appropriate filtersplumbing appropriate filters
Filters can be added by calling Filters can be added by calling FwpmFilterAdd0FwpmFilterAdd0 function function
Filters can specify either permit or block actionFilters can specify either permit or block action
Filters can be plumbed at different layers in the stackFilters can be plumbed at different layers in the stack
Traffic can be secured by invoking IPsec calloutTraffic can be secured by invoking IPsec callout
Secure Socket APIs for socket level securitySecure Socket APIs for socket level security
Callout DriversCallout Drivers
Callout drivers can perform the following tasksCallout drivers can perform the following tasksDeep inspection Deep inspection Packet modificationPacket modificationStream modificationStream modificationData loggingData logging
Callout drivers can be hooked at different layers Callout drivers can be hooked at different layers in the stack, namelyin the stack, namely
Network layerNetwork layerForwarding layerForwarding layerTransport layerTransport layerStream layerStream layerALE layerALE layer
Case Study: Data Logging CalloutCase Study: Data Logging Callout
Initializing a callout driver:Initializing a callout driver:Specify an Unload function in its driver entrySpecify an Unload function in its driver entryOpen a handle to the filter engineOpen a handle to the filter engineAdd callout functions to the filter engine using Add callout functions to the filter engine using FwpmCalloutAdd0FwpmCalloutAdd0 Close the handle to the filter engine using Close the handle to the filter engine using FwpmEngineClose0FwpmEngineClose0
Case Study: Data Logging CalloutCase Study: Data Logging Callout
Callout implements the following functionCallout implements the following functionNotifyfn()Notifyfn() is called by the Filtering Engine is called by the Filtering Engine when a filter that specifies the callout driver’s when a filter that specifies the callout driver’s callout function is added or deletedcallout function is added or deleted
Classifyfn()Classifyfn() is called by the Filtering Engine is called by the Filtering Engine when a filter that specifies the callout when a filter that specifies the callout driver’s callout driver’s callout
Flowdeletefn()Flowdeletefn() is called by the Filtering is called by the Filtering Engine to notify the callout driver when the Engine to notify the callout driver when the flow being processed by it is terminatedflow being processed by it is terminated
Case Study: Data Logging CalloutCase Study: Data Logging Callout
Initialize the callout driver in its Driver Entry functionInitialize the callout driver in its Driver Entry function
VOIDVOID Unload( Unload( IN PDRIVER_OBJECT DriverObject IN PDRIVER_OBJECT DriverObject ); );
NTSTATUSNTSTATUS DriverEntry( DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath IN PUNICODE_STRING RegistryPath ) ){{ ... ...
// Specify the callout driver's Unload function // Specify the callout driver's Unload function DriverObject->DriverUnload = Unload; DriverObject->DriverUnload = Unload;
... ...}}
Case Study: Data Logging CalloutCase Study: Data Logging Callout
Open handle to filtering EngineOpen handle to filtering Engine
FWP_ENGINE_HANDLE engineHandle;FWP_ENGINE_HANDLE engineHandle;NTSTATUS status;NTSTATUS status;
// Open a handle to the filter engine// Open a handle to the filter enginestatus =status = FwpmEngineOpen0( FwpmEngineOpen0( NULL, // The filter engine on the local system NULL, // The filter engine on the local system RPC_C_AUTHN_WINNT, // Use the Windows authentication servi RPC_C_AUTHN_WINNT, // Use the Windows authentication servicece NULL, // Use the calling thread's credentials NULL, // Use the calling thread's credentials NULL, // There are no session-specific parameters NULL, // There are no session-specific parameters &engineHandle // Pointer to a variable to receive the handle &engineHandle // Pointer to a variable to receive the handle ); );
Case Study: Data Logging CalloutCase Study: Data Logging Callout
Notifyfn()Notifyfn()// notifyFn callout function// notifyFn callout functionNTSTATUS NTAPINTSTATUS NTAPI NotifyFn( NotifyFn( IN FWP_NOTIFY_TYPE notifyType, IN FWP_NOTIFY_TYPE notifyType, IN const GUID *filterKey, IN const GUID *filterKey, IN const FWPS_FILTER0 *filter IN const FWPS_FILTER0 *filter ) ){{ // Switch on the type of notification // Switch on the type of notification switch(notifyType) { switch(notifyType) {
// A filter is being added to the filter engine // A filter is being added to the filter engine case FWP_NOTIFY_ADD: case FWP_NOTIFY_ADD:
// Allocate the filter context structure // Allocate the filter context structure context = context = (PFILTER_CONTEXT)ExAllocatePoolWithTag( (PFILTER_CONTEXT)ExAllocatePoolWithTag( NonPagedPool, NonPagedPool, sizeof(FILTER_CONTEXT), sizeof(FILTER_CONTEXT), FILTER_CONTEXT_POOL_TAG); FILTER_CONTEXT_POOL_TAG);
Case Study: Data Logging CalloutCase Study: Data Logging Callout
Notifyfn()Notifyfn()
// Check the result of the memory allocation// Check the result of the memory allocation if (context == NULL) { if (context == NULL) { // Return error // Return error return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES; } } // Initialize the filter context structure // Initialize the filter context structure ... ...
// Associate the filter context structure with the filter // Associate the filter context structure with the filter filter->context = (UINT64)context; filter->context = (UINT64)context;
// Increment the filter count // Increment the filter count InterlockedIncrement(&filterCount); InterlockedIncrement(&filterCount);
break; break; } }
return STATUS_SUCCESS; return STATUS_SUCCESS;
}}
Case Study: Data Logging CalloutCase Study: Data Logging Callout
Classifyfn()Classifyfn() // classifyFn callout function// classifyFn callout function
VOID NTAPI VOID NTAPI ClassifyFn( ClassifyFn( IN const FWPS_INCOMING_VALUES0 *inFixedValues, IN const FWPS_INCOMING_VALUES0 *inFixedValues, IN const FWPS_INCOMING_METADATA_VALUES0 *inMetaValues, IN const FWPS_INCOMING_METADATA_VALUES0 *inMetaValues, IN OUT VOID *layerData, IN OUT VOID *layerData, IN const FWPS_FILTER0 *filter, IN const FWPS_FILTER0 *filter, IN UINT64 flowContext, IN UINT64 flowContext, OUT FWP_ACTION_TYPE *action, OUT FWP_ACTION_TYPE *action, OUT UINT64 *outContext OUT UINT64 *outContext ) ){{ UINT32 index; UINT32 index;
// Increment the total count of discarded packets // Increment the total count of discarded packets InterlockedIncrement(&TotalDiscardCount); InterlockedIncrement(&TotalDiscardCount);
// Loop through the metadata values // Loop through the metadata values for (index = 0; index < inMetaValues- for (index = 0; index < inMetaValues->numMetadataValues; index++) {>numMetadataValues; index++) {
Case Study: Data Logging CalloutCase Study: Data Logging Callout
Classifyfn()Classifyfn()
// Check if this value is a general discard reason// Check if this value is a general discard reason if (inMetaValues->metadataValues[index].fieldId == if (inMetaValues->metadataValues[index].fieldId == FWPS_METADATA_FIELD_GENERAL_DISCARD) { FWPS_METADATA_FIELD_GENERAL_DISCARD) { // Check if discarded by a filter // Check if discarded by a filter if (inMetaValues->metadataValues[index].value == if (inMetaValues->metadataValues[index].value == FwpDiscardFirewallPolicy) { FwpDiscardFirewallPolicy) {
// Increment the count of packets discarded by a filter // Increment the count of packets discarded by a filter InterlockedIncrement(&FilterDiscardCount); InterlockedIncrement(&FilterDiscardCount); } }
// Break out of the for loop // Break out of the for loop break; break; } } } }
// Take no action on the data // Take no action on the data *action = FWP_ACTION_CONTINUE; *action = FWP_ACTION_CONTINUE;}}
Winsock Kernel (WSK)Winsock Kernel (WSK)
WSK GoalsWSK Goals
Simple and consistent APISimple and consistent API
Efficient and scalableEfficient and scalable
Support serviceability of networking componentsSupport serviceability of networking components
Expose full power of the new transport stackExpose full power of the new transport stack
Easy to port to for existing TDI client applicationsEasy to port to for existing TDI client applications
General Sockets programming concepts General Sockets programming concepts SimilarSimilar to user-mode Sockets to user-mode Sockets
NOTNOT targeted to be API-compatible with targeted to be API-compatible with User Mode WinsockUser Mode Winsock
Transport Driver Interface (TDI) Transport Driver Interface (TDI) ShortcomingsShortcomings
TDI Deeply tied to the Windows I/O Manager TDI Deeply tied to the Windows I/O Manager and Object Managerand Object Manager
All TDI Objects are File ObjectsAll TDI Objects are File ObjectsTDI Objects must be created at PASSIVE_LEVEL (IRQL)TDI Objects must be created at PASSIVE_LEVEL (IRQL)However, Transport may indicate new connections at However, Transport may indicate new connections at DISPATCH_LEVELDISPATCH_LEVEL TDI Client must pre-create and manage a cache TDI Client must pre-create and manage a cache of Connection Objects (CO)of Connection Objects (CO)
TDI Clients must use Windows Object Manager APIs TDI Clients must use Windows Object Manager APIs to control TDI Objectsto control TDI Objects
TDI Clients exposed to unnecessary complexityTDI Clients exposed to unnecessary complexity TDI Clients use memory for File Objects for each Address TDI Clients use memory for File Objects for each Address Object (AO) and Connection Object (CO)Object (AO) and Connection Object (CO)
TDI ShortcomingsTDI Shortcomings
Servicing TDI Providers requires rebootServicing TDI Providers requires rebootTDI Providers have no way of detaching TDI Providers have no way of detaching from TDI clientsfrom TDI clients
Each TDI Provider has unique mechanism Each TDI Provider has unique mechanism for surfacing for surfacing OptionsOptions
TDI Clients must have specific knowledge about TDI Clients must have specific knowledge about the underlying TDI Transport Providerthe underlying TDI Transport Provider
Discovery of Transports is difficultDiscovery of Transports is difficultTDI Clients specify bindings at install time and receive TDI Clients specify bindings at install time and receive transport-to-NIC bindingtransport-to-NIC binding notifications notifications
Or: TDI Clients must use hard-coded device names Or: TDI Clients must use hard-coded device names (e.g., \Device\TCP, \Device\UDP, etc.)(e.g., \Device\TCP, \Device\UDP, etc.)
TDI OverviewTDI Overview
Kernel Mode Networking Client Apps
Transport(TCP/IPv4)
\Device\TCP\Device\TCP\Device\UDP\Device\UDP\Device\RAW\Device\RAW
Transport (TCP/IPv6)
\Device\TCP6\Device\TCP6\Device\UDP6\Device\UDP6\Device\RAW6\Device\RAW6
Transport(3rd Party)
\Device\<\Device\<proto>proto><proto> – <proto> – Determined by 3Determined by 3rdrd Party Transport Party Transport ImplementersImplementers
I/O Manager
TDI.SYS
Provided by:
Microsoft
ISV
IHV
Windows Codenamed “Longhorn” Windows Codenamed “Longhorn” Stack OverviewStack Overview
WF
PW
FP
WS2_32.DLL
LSP #1
LSP #2
MSWSOCK.DLL
AFD
TDITDI
Next GenerationTCP/IP Stack
NetBT3rd
Party TDX PrivatePrivateWSK
HTTP.SYS
Winsock 1.0/2.xWinsock 1.0/2.x
SPISPI
SPISPI
SPISPI
WinsockCatalog
UserUser
KernelKernelWSKWSK
LSP = Winsock Layered Service ProviderLSP = Winsock Layered Service Provider
WSK BenefitsWSK BenefitsNo file objects!No file objects!
Can create Sockets at DISPATCH_LEVELCan create Sockets at DISPATCH_LEVEL
Simplified, separate APISimplified, separate APICreate Sockets by specifying {ST, AF, P}Create Sockets by specifying {ST, AF, P}
No more static Device string and cumbersome No more static Device string and cumbersome PFILE_FULL_EA_INFORMATION!PFILE_FULL_EA_INFORMATION!
Connect using SOCKADDR Connect using SOCKADDR No more cumbersome TA_ADDRESS cracking!No more cumbersome TA_ADDRESS cracking!
WSK BenefitsWSK Benefits
No need to attach directly to Transport DeviceNo need to attach directly to Transport DeviceWSK handles Dynamic Transport Discovery WSK handles Dynamic Transport Discovery and Status Notifications via Network Module and Status Notifications via Network Module Registration (NMR)Registration (NMR)Improved Serviceability!Improved Serviceability!
Only element from WDM is use of IRPs for Only element from WDM is use of IRPs for completion mechanism completion mechanism
Insulated from many I/O Manager APIs!Insulated from many I/O Manager APIs!Still receive benefitsStill receive benefits
Driver VerifierDriver VerifierExisting kernel debugger extensionsExisting kernel debugger extensionsI/O request trackingI/O request trackingEase of porting existing TDI clients to WSKEase of porting existing TDI clients to WSK
WSK OverviewWSK Overview
NetworkModule
Registration(NMR)
Winsock Kernel(WSK)
Kernel Mode Networking Client Apps
Transport(3rd Party)
Transport(TCP/IPv4)
Transport (TCP/IPv6)
...
I/O Manager
Provided by:
Microsoft
ISV
IHV
WSK Scenarios: Create Connection (TDI)WSK Scenarios: Create Connection (TDI)
////// Create AO// Create AO////Build FILE_FULL_EA_INFORMATION (TA_ADDRESS)Build FILE_FULL_EA_INFORMATION (TA_ADDRESS)InitializeObjectAttributes (TDI Device Name)InitializeObjectAttributes (TDI Device Name)IoCreateFile(IoCreateFile( &AOHandle,&AOHandle, MAXIMUM_ALLOWED, // MAXIMUM_ALLOWED, // DesiredAccessDesiredAccess &object_attributes,&object_attributes, &io_status_block,&io_status_block, 0, // AllocationSize0, // AllocationSize 0, // FileAttributes0, // FileAttributes 0, // ShareAccess,0, // ShareAccess, FILE_CREATE,FILE_CREATE, 0, // CreateOptions.0, // CreateOptions. ea_buffer,ea_buffer, ea_length,ea_length, CreateFileTypeNone,CreateFileTypeNone, NULL, // NULL, // ExtraCreateParametersExtraCreateParameters create_optionscreate_options ););////// Create CO// Create CO////Build FILE_FULL_EA_INFORMATION Build FILE_FULL_EA_INFORMATION (TdiConnectionContext)(TdiConnectionContext)InitializeObjectAttributes (TDI Device Name)InitializeObjectAttributes (TDI Device Name)IoCreateFile(IoCreateFile( &COHandle,&COHandle, MAXIMUM_ALLOWED, // MAXIMUM_ALLOWED, // DesiredAccessDesiredAccess &object_attributes,&object_attributes, &io_status_block,&io_status_block, 0, // AllocationSize0, // AllocationSize 0, // FileAttributes0, // FileAttributes 0, // ShareAccess,0, // ShareAccess, FILE_CREATE,FILE_CREATE, 0, // CreateOptions.0, // CreateOptions. ea_buffer,ea_buffer, ea_length,ea_length, CreateFileTypeNone,CreateFileTypeNone, NULL, // NULL, // ExtraCreateParametersExtraCreateParameters create_optionscreate_options ););
////// Associate CO to AO// Associate CO to AO////Allocate IRPAllocate IRPGet File and Device Object pointers from Get File and Device Object pointers from CO_FileHandleCO_FileHandleTdiBuildAssociateAddress(CO, AOHandle, TdiBuildAssociateAddress(CO, AOHandle, CompletionRtn/Ctx)CompletionRtn/Ctx)IoCallDriver(IRP)IoCallDriver(IRP)////// Issue connect when AssociateAddress request // Issue connect when AssociateAddress request is completed.is completed.////Allocate IRP or reuse IRP from previous stepAllocate IRP or reuse IRP from previous stepTdiBuildConnect(CO, TA_ADDRESS, TdiBuildConnect(CO, TA_ADDRESS, CompletionRtn/Ctx)CompletionRtn/Ctx)IoCallDriver(IRP) IoCallDriver(IRP)
WSK Scenarios: Create Connection (WSK)WSK Scenarios: Create Connection (WSK)
////// Create and connect a WSK socket in one call// Create and connect a WSK socket in one call////Allocate IRPAllocate IRPIoSetCompletionRoutine(IRP, CompletionRtn/Ctx);IoSetCompletionRoutine(IRP, CompletionRtn/Ctx);WskProviderDispatch->WskSocketConnect(WskProviderDispatch->WskSocketConnect( WskClient,WskClient, SOCK_STREAM,SOCK_STREAM, IPPROTO_TCP,IPPROTO_TCP, LocalAddress, // SOCKADDRLocalAddress, // SOCKADDR RemoteAddress, // SOCKADDRRemoteAddress, // SOCKADDR 0, // Flags0, // Flags SocketCallbackContext,SocketCallbackContext, SocketCallbackDispatch,SocketCallbackDispatch, Process,Process, Thread,Thread, SecurityDescriptor,SecurityDescriptor, IRPIRP ););
WSK Scenarios: WSK Socket ControlWSK Scenarios: WSK Socket Control
////// Setting SO_RCVBUF socket option// Setting SO_RCVBUF socket option////ULONG rcvbufsize = 16384;ULONG rcvbufsize = 16384;Allocate IRP;Allocate IRP;IoSetCompletionRoutine(IRP, CompletionRtn/Ctx);IoSetCompletionRoutine(IRP, CompletionRtn/Ctx);WskSocketDispatch-> WskControlSocket (WskSocketDispatch-> WskControlSocket ( WskSocket,WskSocket, WskSetOption, // RequestType: set, get, ioctlWskSetOption, // RequestType: set, get, ioctl SO_RCVBUF, // OptionNameSO_RCVBUF, // OptionName SOL_SOCKET, // LevelSOL_SOCKET, // Level sizeof(rcvbufsize), // InputSizesizeof(rcvbufsize), // InputSize &rcvbufsize, // InputBuffer&rcvbufsize, // InputBuffer 0, // OutputSize0, // OutputSize NULL, // OutputBufferNULL, // OutputBuffer NULL, // OutputSizeReturnedNULL, // OutputSizeReturned IRPIRP ););
Call To ActionCall To Action
WFPWFPExplore WFP API documentation in the WDK Explore WFP API documentation in the WDK for kernel APIs and SDK for user APIsfor kernel APIs and SDK for user APIs
Use WFP APIs instead of filter and firewall hooksUse WFP APIs instead of filter and firewall hooks
Consider using Callout drivers instead of NDIS Consider using Callout drivers instead of NDIS and LSPsand LSPs
WSKWSKExplore the WSK API Documentation in the Windows Explore the WSK API Documentation in the Windows Driver Kit (WDK)Driver Kit (WDK)
Sample WSK Client planned for Beta 2 WDKSample WSK Client planned for Beta 2 WDK
Consider using WSK for new KM networking needsConsider using WSK for new KM networking needs
Consider migrating old TDI client code to WSKConsider migrating old TDI client code to WSK
Community ResourcesCommunity Resources
Windows Hardware and Driver Central (WHDC)Windows Hardware and Driver Central (WHDC)www.microsoft.com/whdc/default.mspx www.microsoft.com/whdc/default.mspx
Technical CommunitiesTechnical Communitieswww.microsoft.com/communities/products/default.mspx www.microsoft.com/communities/products/default.mspx
Non-Microsoft Community SitesNon-Microsoft Community Siteswww.microsoft.com/communities/related/default.mspx www.microsoft.com/communities/related/default.mspx
Microsoft Public NewsgroupsMicrosoft Public Newsgroupswww.microsoft.com/communities/newsgroupswww.microsoft.com/communities/newsgroups
Technical Chats and WebcastsTechnical Chats and Webcastswww.microsoft.com/communities/chats/default.mspxwww.microsoft.com/communities/chats/default.mspx
www.microsoft.com/webcastswww.microsoft.com/webcasts
Microsoft BlogsMicrosoft Blogswww.microsoft.com/communities/blogswww.microsoft.com/communities/blogs
Additional ResourcesAdditional Resources
E-MailE-MailWFP: wfp @ microsoft.comWFP: wfp @ microsoft.com
WSK: wskapi @ microsoft.comWSK: wskapi @ microsoft.com
Web ResourcesWeb ResourcesJoin the WFP beta programJoin the WFP beta program
Go to Go to http://http://beta.microsoft.combeta.microsoft.com
Choose the Guest ID sign-up optionChoose the Guest ID sign-up option
Enter the Guest ID: WFPBeta5Enter the Guest ID: WFPBeta5
Fill out the WFP beta program sign up surveyFill out the WFP beta program sign up survey