As I have promised in my previous post, I am making available a C++ console application to troubleshoot named pipes endpoints in WCF. Below is a screenshot of the application:
Application logic:
Post detailing the problem:
http://blogs.msdn.com/b/rodneyviana/archive/2011/03/22/named-pipes-in-wcf-are-named-but-not-by-you-and-how-to-find-the-actual-windows-object-name.aspx
Source Code is as shown below (subject to this license: http://rodneyviana.codeplex.com/license).
// ReadMemory.cpp : Defines the entry point for the console application. //
#include "stdafx.h"
void NormalizeEndPoint(const std::wstring &source, std::wstring& normal) { normal.assign(source);
if(!normal.compare(0, 10, L"net.pipe://")) { normal.clear(); return; }
int hoststart = normal.find_first_of(L"//"); int hostend = normal.find(L"/", hoststart+2);
std::wstring ending(normal.substr(hostend)); std::wstring starting(normal.substr(0, hoststart).append(L"//+")); std::transform(ending.begin(), ending.end(), ending.begin(), (int(*)(int))std::toupper); std::wstring normalized(starting.append(ending)); if(normalized.substr(normalized.length()-1).compare(L"/")) { normalized.append(L"/"); } normal.assign(normalized); return;
}
void ShowSyntax(bool SyntaxError) { std::wprintf(L"ReadMemory version 1.0\n"); std::wprintf(L"Written by Rodney Viana - http://blogs.msdn.com/rodneyviana\n"); std::wprintf(L"\n"); if(SyntaxError) std::wprintf(L"Syntax Error\n\n");
std::wprintf(L"Syntax:\n"); std::wprintf(L"ReadMemory <PipeNameEndPoint> | -file <MappedMemoryFile>\n"); std::wprintf(L"Where:\t<PipeNameEndPoint> is a endpoint for a net.pipe in WCF in\n\t the format net.pipe://host/path\n"); std::wprintf(L"\t<MappedMemoryFile> is a memory mapped file\n"); std::wprintf(L"\n"); std::wprintf(L"Examples\n"); std::wprintf(L"\tReadMemory net.pipe://localhost/Service/Service1\n"); std::wprintf(L"\tReadMemory -file \"net.pipe:EbmV0LnBpcGU6Ly8rLzhFNjFFRUM5LUYxOUEtNEIxNy04REE4LTM5NTc1QzhGMTU4QS8=\"\n");
int _tmain(int argc, _TCHAR* argv[]) { if(argc < 2) { ShowSyntax(false); return 0; }
if(argc > 3) { ShowSyntax(true); return 1;
std::wstring original; std::wstring normalized; std::wstring mapFile;
if(argc == 2) { original.append(argv[1]); NormalizeEndPoint(original, normalized); std::wprintf(L"\nOriginal Endpoint: %s", original.c_str());
std::wprintf(L"\nNominal Endpoint: %s", normalized.c_str());
char base64A[1000];
CW2A ansiNormal(normalized.c_str()); int size = 1000; Base64Encode((BYTE*)ansiNormal.m_psz, normalized.length(), base64A, &size, ATL_BASE64_FLAG_NOCRLF | ATL_BASE64_FLAG_NOPAD );
base64A[size]='='; base64A[size+1]='\0';
CA2W base64W(base64A);
mapFile.append(L"net.pipe:E"); mapFile.append(base64W.m_psz);
if(argc == 3) { std::wstring force(argv[1]); std::transform(force.begin(), force.end(), force.begin(), (int(*)(int))std::toupper); if(!force.compare(0, 4, L"-FILE")) { ShowSyntax(true); return 2; }
mapFile.append(argv[2]);
//original.append(L"net.pipe://localhost/TradeService/Service1");
std::wprintf(L"\nMapped Memory Object Name: %s", mapFile.c_str());
HANDLE map = OpenFileMapping(FILE_MAP_READ, FALSE, mapFile.c_str()); MEMORY_BASIC_INFORMATION mi; if(map) { std::wprintf(L"\nGood News: Mapped memory Object was found. It shows that Host is enabled.");
PVOID contents = MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0); SIZE_T s = VirtualQuery(contents, &mi, sizeof(mi));
if(s<sizeof(GUID)+4) { std::wprintf(L"\nMapped memory Object seems to be corrupted. Restart your WCF Host.\n"); } PBYTE bytes = ((PBYTE)contents)+4;
std::wprintf(L"\nRaw Bytes:\n");
if(contents) { for(SIZE_T i=0;i<sizeof(GUID);i++) { printf("%02x ", *(bytes+i)); }
std::wprintf(L"\n"); for(SIZE_T i=sizeof(GUID);i<s-4;i++) { printf("%02x ", *(bytes+i)); } GUID *guid = (GUID*)bytes; RPC_WSTR guidStr;
UuidToString(guid, &guidStr); std::wprintf(L"\nActual Named Pipe Name: %s", guidStr); std::wprintf(L"\nFull Named Pipe Name: \\Device\\NamedPipe\\%s", guidStr); std::wstring localPipe(_T("\\\\.\\pipe\\")); localPipe.append((LPWSTR)guidStr);
std::wprintf(L"\nAttempting to connect to Named Pipe for 20 seconds ...\n");
if(!WaitNamedPipe(localPipe.c_str(), 20000)) { std::wprintf(L"\nBad News: Unable to connect to local pipe: %s.\nReason: Time out.", localPipe.c_str());
} else { std::wprintf(L"\nGood News: Local pipe \"%s\" is alive.", localPipe.c_str()); HANDLE pipe;
std::wprintf(L"\nAttempting to open Named Pipe...\n");
pipe = CreateFile(localPipe.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, NULL);
if(pipe == INVALID_HANDLE_VALUE) { std::wprintf(L"\nBad News: Unable to open local pipe: %s.\nLast Error: %i.", localPipe.c_str(), GetLastError()); } else { std::wprintf(L"\nGood News: Named Pipe opened successfully.\n");
TCHAR* send = L"<bad><\\bad>\n"; DWORD bytesUsed;
if(!WriteFile(pipe, (void*)send, wcslen(send)*sizeof(TCHAR), &bytesUsed, NULL)) { std::wprintf(L"\nBad News: Unable to send bytes.\n");
} else { std::wprintf(L"\nGood News: Pipe accepted bytes\n"); std::wprintf(L"\nTest completed successfully!\n");
} CloseHandle(pipe); }
} else { std::wprintf(L"\nBad News: Host is not informing pipe id."); } UnmapViewOfFile(map); } else { std::wprintf(L"\nBad News: Mapped File %s was not found. LastError: %x", mapFile.c_str(), GetLastError());
} CloseHandle(map); std::wprintf(L"\n"); return 0; }
Download the project/executable here:
WCF Named Pipes Identification