Solved

The procedure entry point could not be located

Posted on 2010-08-22
15
2,689 Views
Last Modified: 2012-05-10
Hi,

I am trying to run this process in VS2008, window xp OS, but I'm getting the following error:
The procedure entry point GetNamedPipeClientProcessId could not be located in the dynamic link library KERNEL32.dll. I'm new to window programming and don't have any idea why this is happening.
Can you please help with this error?

Thanks in advance.
/*  Chapter 11. ServerNP.

 *	Multi-threaded command line server. Named pipe version

 *	Usage:	Server [UserName GroupName]

 *	ONE THREAD AND PIPE INSTANCE FOR EVERY CLIENT. */



#include "Everything.h"

#include "ClientServer.h" /* Request and Response messages defined here */



typedef struct {				/* Argument to a server thread. */

	HANDLE hNamedPipe;			/* Named pipe instance. */

	DWORD threadNumber;

	TCHAR tempFileName[MAX_PATH]; /* Temporary file name. */

} THREAD_ARG;

typedef THREAD_ARG *LPTHREAD_ARG;



volatile static int shutDown = 0;

static DWORD WINAPI Server (LPTHREAD_ARG);

static DWORD WINAPI Connect (LPTHREAD_ARG);

static DWORD WINAPI ServerBroadcast (LPLONG);

static BOOL  WINAPI Handler (DWORD);

static TCHAR shutRequest[] = _T("$ShutDownServer");

static THREAD_ARG threadArgs[MAX_CLIENTS];



_tmain (int argc, LPTSTR argv[])

{

	/* MAX_CLIENTS is defined in ClientServer.h. */

	/* Currently limited to MAXIMUM_WAIT_OBJECTS WaitForMultipleObjects */

	/* is used by the main thread to wait for the server threads */



	HANDLE hNp, hMonitor, hSrvrThread[MAX_CLIENTS];

	DWORD iNp, monitorId, threadId;

	DWORD AceMasks[] =	/* Named pipe access rights - described in Chapter 15 */

		{STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0X1FF, 0, 0 };

	LPSECURITY_ATTRIBUTES pNPSA = NULL;



	if (!WindowsVersionOK (6, 0)) 

		ReportError (_T("This program requires Windows NT 6.0 or greater"), 1, FALSE);



	/* Console control handler to permit server shut down */

	if (!SetConsoleCtrlHandler (Handler, TRUE))

		ReportError (_T("Cannot create Ctrl handler"), 1, TRUE);



	/* Pipe security is commented out for simplicity - See chapter 16 */

//	if (argc == 4)		/* Optional pipe security - Uses a simpler function. */

//		pNPSA = InitializeAccessOnlySA (0440, argv[1], argv[2], AceMasks, &hSecHeap);

			

	/* Create a thread broadcast pipe name periodically. */

	hMonitor = (HANDLE) _beginthreadex (NULL, 0, ServerBroadcast, NULL, 0, &monitorId);



	/*	Create a pipe instance for every server thread.

	 *	Create a temp file name for each thread.

	 *	Create a thread to service that pipe. */



	for (iNp = 0; iNp < MAX_CLIENTS; iNp++) {

		hNp = CreateNamedPipe ( SERVER_PIPE, PIPE_ACCESS_DUPLEX,

				PIPE_READMODE_MESSAGE | PIPE_TYPE_MESSAGE | PIPE_WAIT,

				MAX_CLIENTS, 0, 0, INFINITE, pNPSA);



		if (hNp == INVALID_HANDLE_VALUE)

			ReportError (_T ("Failure to open named pipe."), 1, TRUE);

		threadArgs[iNp].hNamedPipe = hNp;

		threadArgs[iNp].threadNumber = iNp;

		GetTempFileName (_T ("."), _T ("CLP"), 0, threadArgs[iNp].tempFileName);

		hSrvrThread[iNp] = (HANDLE)_beginthreadex (NULL, 0, Server,

				&threadArgs[iNp], 0, &threadId);

		if (hSrvrThread[iNp] == NULL)

			ReportError (_T ("Failure to create server thread."), 2, TRUE);

	}

	

	/* Wait for all the threads to terminate. */



	WaitForMultipleObjects (MAX_CLIENTS, hSrvrThread, TRUE, INFINITE);

	_tprintf (_T ("All Server worker threads have shut down.\n"));



	WaitForSingleObject (hMonitor, INFINITE);

	_tprintf (_T ("Monitor thread has shut down.\n"));



	CloseHandle (hMonitor);

	for (iNp = 0; iNp < MAX_CLIENTS; iNp++) { 

		/* Close pipe handles and delete temp files */

		/* Closing temp files is redundant, as the worker threads do it */

		CloseHandle (hSrvrThread[iNp]);

		DeleteFile (threadArgs[iNp].tempFileName);

	}



	_tprintf (_T ("Server process will exit.\n"));

	return 0;

}





static DWORD WINAPI Server (LPTHREAD_ARG pThArg)



/* Server thread function. There is a thread for every potential client. */

{

	/* Each thread keeps its own request, response,

		and bookkeeping data structures on the stack. 

		Also, each thread creates an additional "connect thread"

		so that the main worker thread can test the shut down flag

		periodically while waiting for a client connection. */



	HANDLE hNamedPipe, hTmpFile = INVALID_HANDLE_VALUE, hConTh = NULL, hClient;

	DWORD nXfer, conThStatus, clientProcessId;

	STARTUPINFO startInfoCh;

	SECURITY_ATTRIBUTES tempSA = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};

	PROCESS_INFORMATION procInfo;

	FILE *fp;

	REQUEST request;

	RESPONSE response;

	TCHAR clientName[256];



	GetStartupInfo (&startInfoCh);

	hNamedPipe = pThArg->hNamedPipe;



	while (!shutDown) { 	/* Connection loop */



		/* Create a connection thread, and wait for it to terminate */

		/* Use a timeout on the wait so that the shut down flag can be tested */

		hConTh = (HANDLE)_beginthreadex (NULL, 0, Connect, pThArg, 0, NULL);

		if (hConTh == NULL) {

			ReportError (_T("Cannot create connect thread"), 0, TRUE);

			_endthreadex(2);

		}



		/* Wait for a client connection. */	

		while (!shutDown && WaitForSingleObject (hConTh, CS_TIMEOUT) == WAIT_TIMEOUT) 

			{ /* Empty loop body */};

		if (shutDown) _tprintf (_T("Thread %d received shut down\n"), pThArg->threadNumber);

		if (shutDown) continue;	/* Flag could also be set by a different thread */



		CloseHandle (hConTh); hConTh = NULL;

		/* A connection now exists */

        

		if (!GetNamedPipeClientComputerName(pThArg->hNamedPipe, clientName, sizeof(clientName))) {

			_tcscpy_s(clientName, sizeof(clientName)/sizeof(TCHAR)-1, _T("localhost"));

		}

        GetNamedPipeClientProcessId(pThArg->hNamedPipe, &clientProcessId);

		_tprintf(_T("Connect to client process id: %d on computer: %s\n"), clientProcessId, clientName);

        

		while (!shutDown && ReadFile (hNamedPipe, &request, RQ_SIZE, &nXfer, NULL)) {

			/* Receive new commands until the client disconnects */

			_tprintf(_T("Command from client thread: %d. %s\n"), clientProcessId, request.record);

			shutDown = shutDown || (_tcscmp (request.record, shutRequest) == 0);

			if (shutDown)  continue;



			/* Open the temporary results file used by all connections to this instance. */

			hTmpFile = CreateFile (pThArg->tempFileName, GENERIC_READ | GENERIC_WRITE,

				FILE_SHARE_READ | FILE_SHARE_WRITE, &tempSA,

				CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL);

			if (hTmpFile == INVALID_HANDLE_VALUE) { /* About all we can do is stop the thread */

				ReportError (_T("Cannot create temp file"), 0, TRUE);

				_endthreadex(1);

			}



			/* Main command loop */

			/* Create a process to carry out the command. */

			startInfoCh.hStdOutput = hTmpFile;

			startInfoCh.hStdError = hTmpFile;

			startInfoCh.hStdInput = GetStdHandle (STD_INPUT_HANDLE);

			startInfoCh.dwFlags = STARTF_USESTDHANDLES;



			if (!CreateProcess (NULL, request.record, NULL,

				NULL, TRUE, /* Inherit handles. */

				0, NULL, NULL, &startInfoCh, &procInfo)) {

					PrintMsg (hTmpFile, _T("ERR: Cannot create process."));

					procInfo.hProcess = NULL;

			}



			CloseHandle(hTmpFile);  /* The child process is using the temp file, but the parent handle isn't needed */

			if (procInfo.hProcess != NULL ) { /* Server process is running */

				CloseHandle (procInfo.hThread);

				WaitForSingleObject (procInfo.hProcess, INFINITE);

				CloseHandle (procInfo.hProcess);

			}

			

			/* Respond a line at a time. It is convenient to use

				C library line-oriented routines at this point. */



			if (_tfopen_s (&fp, pThArg->tempFileName, _T("r")) != 0) {	

				_tprintf (_T("Temp output file is: %s.\n"), pThArg->tempFileName);

				_tperror (_T("Failure to open command output file."));

				break;  /* Try the next command. */

			}



			/* Avoid an "information discovery" security exposure. */

			/* ZeroMemory(&response, sizeof(response));  */

			while (_fgetts (response.record, MAX_RQRS_LEN, fp) != NULL) {

				response.rsLen = (LONG32)(strlen(response.record) + 1);

				WriteFile (hNamedPipe, &response, response.rsLen + sizeof(response.rsLen), &nXfer, NULL);

			}

			/* Write a terminating record. Messages use 8-bit characters, not UNICODE */

			response.record[0] = '\0';

			response.rsLen = 0;

			WriteFile (hNamedPipe, &response, sizeof(response.rsLen), &nXfer, NULL); 



			FlushFileBuffers (hNamedPipe);

			fclose (fp);



		}   /* End of main command loop. Get next command */



		/* Client has disconnected or there has been a shut down requrest */

		/* Terminate this client connection and then wait for another */

		FlushFileBuffers (hNamedPipe);

		DisconnectNamedPipe (hNamedPipe);

	}



	/*  Force the connection thread to shut down if it is still active */

    if (hConTh != NULL) {

        GetExitCodeThread (hConTh, &conThStatus);

	    if (conThStatus == STILL_ACTIVE) {

		    hClient = CreateFile (SERVER_PIPE, GENERIC_READ | GENERIC_WRITE, 0, NULL,

			    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

		    if (hClient != INVALID_HANDLE_VALUE) CloseHandle (hClient);

		    WaitForSingleObject (hConTh, INFINITE);

        }

	}





/*	Comments about terminating the connection thread:

	There is an issue with the fact that the Connect thread

	could still be running. You would like to terminate it, but then 

	there would not be a clean thread shut down, and, for example, 

	DLL entry points would not be called, resulting in potential resource leaks.

	Now, in this case, the connection thread is minimal, so there should be

	no harm, but, here we've used a different approach:



	The connection thread can be resumed by having the server

	act like a client and perform a CreateFile to get a (very) short lived 

	connection, allowing the connection thread to shut down.



    Unfortunately, there is a problem here; any Connect thread could respond,

	not the one on the server instance we're interested in. We've ignored that

	here as there's only on connect thread.



	Nonetheless, here are a couple of other solutions that are tempting

	to try, but they both have problems.

	

	IDEA 1. Close the named pipe handle. Perhaps, that will cause the ConnectNamedPipe

	call to fail and the Connect thread can terminate. Unfortunately, CloseHandle 

	blocks while there is an active ConnectNamedPipe call.

		CloseHandle (hNamedPipe);  // Don't do this! It could block.

	

	IDEA 2. Terminate the thread. The problem is that DLL entry points will

	not be called, resulting in potential resource leaks mentioned above.



	NOTE: DLL entry points were discussed in Chapter 5 but have not been illustrated

	yet. There is an example in Chapter 12.



	IDEA 3. Use thread cancellation using asynch proc calls (Chapter 10).

	Unfortunately, the client may not be in an alertable wait state.



*/

	_tprintf (_T("Thread %d shutting down.\n"), pThArg->threadNumber);

	/* End of command processing loop. Free resources and exit from the thread. */

	CloseHandle (hTmpFile); hTmpFile = INVALID_HANDLE_VALUE;

	if (!DeleteFile (pThArg->tempFileName)) {

		ReportError (_T("Failed deleting temp file."), 0, TRUE);

	}

	_tprintf (_T ("Exiting server thread number %d.\n"), pThArg->threadNumber);

	return 0;

}





static DWORD WINAPI Connect (LPTHREAD_ARG pThArg)

{

	BOOL fConnect;

	/*	Pipe connection thread that allows the server worker thread 

		to poll the shut down flag. */

	fConnect = ConnectNamedPipe (pThArg->hNamedPipe, NULL);

	_endthreadex (0);

	return 0;	/* Suppress a compiler warning message. */ 

}





static DWORD WINAPI ServerBroadcast (LPLONG pNull)

{

	MS_MESSAGE MsNotify;

	DWORD nXfer, iNp;

	HANDLE hMsFile;



	/* Open the mailslot for the MS "client" writer. */

	while (!shutDown) { /* Run as long as there are server threads */

		/* Wait for another client to open a mailslot. */

		Sleep (CS_TIMEOUT);

		/* NOTE (Oct 12, 2001). The mailslot CreateFile uses GENERIC_WRITE

		   but not GENERIC_READ. GENERIC_READ will work on Windows NT/2000/XP,

		   but will fail ("BAD PARAMETER") on Windows 9x/Me. Now, this particular

		   program is not designed for 9x/Me since it is a named pipe server, but

		   there are many cases is which a mailslot client would run on 9x/Me, so

		   do not use GENERIC_READ when creating a mailslot client file */

		hMsFile = CreateFile (MS_CLTNAME, GENERIC_WRITE,

				FILE_SHARE_READ,

				NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

		if (hMsFile == INVALID_HANDLE_VALUE) continue;



		/* Send out the message to the mailslot. */



		MsNotify.msStatus = 0;

		MsNotify.msUtilization = 0;

		_tcsncpy_s (MsNotify.msName, sizeof(MsNotify.msName)/sizeof(TCHAR), SERVER_PIPE, _TRUNCATE);

		if (!WriteFile (hMsFile, &MsNotify, MSM_SIZE, &nXfer, NULL))

			ReportError (_T ("Server MS Write error."), 13, TRUE);

		CloseHandle (hMsFile);

	}



	/* Cancel all outstanding NP I/O commands. See Chapter 14 for CancelIoEx */

	_tprintf (_T("Shut down flag set. Cancel all outstanding I/O operations.\n"));

	/* This is an NT6 dependency. On Windows XP, outstanding NP I/O operations hang. */

	for (iNp = 0; iNp < MAX_CLIENTS; iNp++) {

		CancelIoEx (threadArgs[iNp].hNamedPipe, NULL);

	}

	_tprintf (_T ("Shuting down monitor thread.\n"));



	_endthreadex (0);

	return 0;

}





BOOL WINAPI Handler (DWORD CtrlEvent)

{

	/* shut down the system */

	_tprintf (_T("In console control handler\n"));

	InterlockedIncrement(&shutDown);

	return TRUE;

}

Open in new window

0
Comment
Question by:vielkacarolina1239
  • 8
  • 5
  • 2
15 Comments
 
LVL 62

Accepted Solution

by:
☠ MASQ ☠ earned 500 total points
ID: 33496947
The version of Kernel32.dll in XP doesn't support the function "GetNamedPipeClientProcessId"
This is found in Kernel32.dll from Vista onward
http://msdn.microsoft.com/en-us/library/aa365440(VS.85).aspx
0
 
LVL 32

Expert Comment

by:phoffric
ID: 33496948
I'm not a MS Windows programmer but I'll take a guess that you did not include all your headers that you may need. Try adding some of these if you haven't already done so.
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
0
 
LVL 32

Expert Comment

by:phoffric
ID: 33496962
0
 
LVL 62

Expert Comment

by:☠ MASQ ☠
ID: 33496981
This should work in a VS2008/Vista combination but won't with XP - as a learning exercise (which is what this appears to be) using XP is the wrong way to go unless your project is to produce a similar routine on XP using different function calls.
 
I guess that's the error explained.  The fix is use a different client OS unless you are forced to find a workaround - which would be a rewrite of the example code you posted.
0
 

Author Comment

by:vielkacarolina1239
ID: 33497020
This is a learning exercise, I was told to use xp.
0
 

Author Comment

by:vielkacarolina1239
ID: 33497042
Thanks for the info.
0
 
LVL 62

Expert Comment

by:☠ MASQ ☠
ID: 33497063
Are you running this one on XP? - it's the Server version.
2008 supports "GetNamedPipeClientProcessId"
For XP you run
http://fmgroup.polito.it/murciano/teachings/sp/CHAPTR11/clientNP.C
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 

Author Comment

by:vielkacarolina1239
ID: 33497113
xp professional, no the server version.
0
 

Author Comment

by:vielkacarolina1239
ID: 33497121
I meant to say, xp professional, no server 2008.
0
 

Author Comment

by:vielkacarolina1239
ID: 33497127
clientNP.c is the part of the project
0
 
LVL 62

Expert Comment

by:☠ MASQ ☠
ID: 33497130
The code in your question should run on Windows Server 2008, the code in my link is for XP (Client)
0
 

Author Comment

by:vielkacarolina1239
ID: 33497141
I was told to use both in xp. clientNP works fine.
0
 

Author Comment

by:vielkacarolina1239
ID: 33497159
I guess that I won’t be able to run serverNP.c on xp professional if there is not a way around it.
0
 
LVL 62

Assisted Solution

by:☠ MASQ ☠
☠ MASQ ☠ earned 500 total points
ID: 33497186
I would still say you can't call "GetNamedPipeClientProcessId" in XP's Kernel32.dll, unless VS2008 has installed another version which supports the function I'm afraid you might need to go back to your tutor with this.
Perhaps someone else can come up with another explanation ...
0
 

Author Comment

by:vielkacarolina1239
ID: 33497213
Thanks, I'll go back to him.
0

Featured Post

Comprehensive Backup Solutions for Microsoft

Acronis protects the complete Microsoft technology stack: Windows Server, Windows PC, laptop and Surface data; Microsoft business applications; Microsoft Hyper-V; Azure VMs; Microsoft Windows Server 2016; Microsoft Exchange 2016 and SQL Server 2016.

Join & Write a Comment

Can I legally transfer my OEM version of Windows to another PC?  (AKA - Can I put a new systemboard in my OEM PC?) Few of us are both IT and legal experts but we all have our own views of Microsoft's licensing rules and how they apply.  There are…
For both online and offline retail, the cross-channel business is the most recent pattern in the B2C trade space.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now