Blame src/win32_support.c

Packit c32a2d
#include "config.h"
Packit c32a2d
#include "mpg123app.h"
Packit c32a2d
#include "debug.h"
Packit c32a2d
Packit c32a2d
#ifdef WANT_WIN32_UNICODE
Packit c32a2d
Packit c32a2d
/* Obscure and undocumented call from MS C Runtime "MSVCRT.DLL" */
Packit c32a2d
typedef struct
Packit c32a2d
{
Packit c32a2d
	int newmode;
Packit c32a2d
} _startupinfo;
Packit c32a2d
Packit c32a2d
/* XP and later has an int return though */
Packit c32a2d
void __cdecl __declspec(dllimport) __wgetmainargs (
Packit c32a2d
	int *_Argc,
Packit c32a2d
	wchar_t ***_Argv,
Packit c32a2d
	wchar_t ***_Env,
Packit c32a2d
	int _DoWildCard,
Packit c32a2d
	_startupinfo * _StartInfo
Packit c32a2d
);
Packit c32a2d
Packit c32a2d
int win32_cmdline_utf8(int * argc, char *** argv)
Packit c32a2d
{
Packit c32a2d
	int argcounter;
Packit c32a2d
	wchar_t **argv_wide;
Packit c32a2d
	wchar_t **env;
Packit c32a2d
	char *argvptr;
Packit c32a2d
	_startupinfo startup;
Packit c32a2d
Packit c32a2d
	/* That's too lame. */
Packit c32a2d
	if(argv == NULL || argc == NULL) return -1;
Packit c32a2d
Packit c32a2d
	startup.newmode = 0;
Packit c32a2d
	__wgetmainargs(argc, &argv_wide,&env,1, &startup);
Packit c32a2d
	*argv = (char **)calloc(sizeof (char *), *argc);
Packit c32a2d
	if(*argv == NULL){ error("Cannot allocate memory for command line."); return -1; }
Packit c32a2d
Packit c32a2d
	for(argcounter = 0; argcounter < *argc; argcounter++)
Packit c32a2d
	{
Packit c32a2d
		win32_wide_utf8(argv_wide[argcounter], &argvptr, NULL);
Packit c32a2d
		(*argv)[argcounter] = argvptr;
Packit c32a2d
	}
Packit c32a2d
	return 0;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
void win32_cmdline_free(int argc, char **argv)
Packit c32a2d
{
Packit c32a2d
	int i;
Packit c32a2d
	if(argv == NULL) return;
Packit c32a2d
	for(i=0; i
Packit c32a2d
}
Packit c32a2d
#endif /* WANT_WIN32_UNICODE */
Packit c32a2d
Packit c32a2d
#ifdef _WIN32
Packit c32a2d
void win32_set_priority (const int arg)
Packit c32a2d
{
Packit c32a2d
	DWORD proc_result = 0;
Packit c32a2d
	HANDLE current_proc = NULL;
Packit c32a2d
	if(arg)
Packit c32a2d
	{
Packit c32a2d
		if((current_proc = GetCurrentProcess()))
Packit c32a2d
		{
Packit c32a2d
			switch(arg)
Packit c32a2d
			{
Packit c32a2d
				case -2: proc_result = SetPriorityClass(current_proc, IDLE_PRIORITY_CLASS); break;  
Packit c32a2d
				case -1: proc_result = SetPriorityClass(current_proc, BELOW_NORMAL_PRIORITY_CLASS); break;  
Packit c32a2d
				case 0: proc_result = SetPriorityClass(current_proc, NORMAL_PRIORITY_CLASS); break; /*default priority*/
Packit c32a2d
				case 1: proc_result = SetPriorityClass(current_proc, ABOVE_NORMAL_PRIORITY_CLASS); break;
Packit c32a2d
				case 2: proc_result = SetPriorityClass(current_proc, HIGH_PRIORITY_CLASS); break;
Packit c32a2d
				case 3: proc_result = SetPriorityClass(current_proc, REALTIME_PRIORITY_CLASS); break;
Packit c32a2d
				default: fprintf(stderr,"Unknown priority class specified\n");
Packit c32a2d
			}
Packit c32a2d
			if(!proc_result) fprintf(stderr,"SetPriorityClass failed\n");
Packit c32a2d
		}
Packit c32a2d
		else fprintf(stderr,"GetCurrentProcess failed\n");
Packit c32a2d
	}
Packit c32a2d
}
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#ifdef WANT_WIN32_FIFO
Packit c32a2d
static HANDLE fifohandle;
Packit c32a2d
static OVERLAPPED ov1;
Packit c32a2d
Packit c32a2d
VOID CALLBACK ReadComplete(
Packit c32a2d
	DWORD dwErrorCode,
Packit c32a2d
	DWORD dwNumberOfBytesTransfered,
Packit c32a2d
	LPOVERLAPPED lpOverlapped
Packit c32a2d
)
Packit c32a2d
{
Packit c32a2d
	/* Reset OVERLAPPED structure */
Packit c32a2d
	debug("ReadFileEx completed");
Packit c32a2d
	memset(lpOverlapped,0,sizeof(OVERLAPPED));
Packit c32a2d
	return;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
ssize_t win32_fifo_read(void *buf, size_t nbyte)
Packit c32a2d
{
Packit c32a2d
	int check;
Packit c32a2d
	DWORD readbuff;
Packit c32a2d
	DWORD available;
Packit c32a2d
	debug1("Reading pipe handle %p", fifohandle);
Packit c32a2d
	if (!fifohandle) return 0;
Packit c32a2d
Packit c32a2d
	available = win32_fifo_read_peek(NULL);
Packit c32a2d
	if (!available) return 0;
Packit c32a2d
Packit c32a2d
	/* This looks more like a hack than a proper check */
Packit c32a2d
	readbuff = (nbyte > available) ? available : nbyte;
Packit c32a2d
	debug("Starting ReadFileEx");
Packit c32a2d
	check = ReadFileEx(fifohandle,buf,readbuff,&ov1,&ReadComplete);
Packit c32a2d
	WaitForSingleObjectEx(fifohandle,INFINITE,TRUE);
Packit c32a2d
	debug1("Read %ld bytes from pipe", readbuff);
Packit c32a2d
	return (!check) ? 0 : readbuff;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
/* function should be able to tell if bytes are
Packit c32a2d
   available and return immediately on overlapped
Packit c32a2d
   asynchrounous pipes, like unix select() */
Packit c32a2d
DWORD win32_fifo_read_peek(struct timeval *tv)
Packit c32a2d
{
Packit c32a2d
	DWORD ret = 0;
Packit c32a2d
	DWORD err, timer;
Packit c32a2d
Packit c32a2d
	timer = (tv) ? tv -> tv_sec * 1000 : INFINITE;
Packit c32a2d
Packit c32a2d
	debug1("Peeking on pipe handle %p", fifohandle);
Packit c32a2d
Packit c32a2d
	SetLastError(0);
Packit c32a2d
	if(!fifohandle) return 0;
Packit c32a2d
		PeekNamedPipe(fifohandle, NULL, 0, NULL, &ret, NULL);
Packit c32a2d
	err =  GetLastError();
Packit c32a2d
	debug1("Waiting %ld msec for pipe to be ready", timer);
Packit c32a2d
	debug1("GetLastError was %ld", err);
Packit c32a2d
	if(err == ERROR_BROKEN_PIPE)
Packit c32a2d
	{
Packit c32a2d
		debug("Broken pipe, disconnecting");
Packit c32a2d
		DisconnectNamedPipe(fifohandle);
Packit c32a2d
		ConnectNamedPipe(fifohandle,&ov1;;
Packit c32a2d
		WaitForSingleObjectEx(fifohandle,timer,TRUE);
Packit c32a2d
	}
Packit c32a2d
	else if(err == ERROR_BAD_PIPE)
Packit c32a2d
	{
Packit c32a2d
		debug("Bad pipe, Waiting for connect");
Packit c32a2d
		DisconnectNamedPipe(fifohandle);
Packit c32a2d
		ConnectNamedPipe(fifohandle,&ov1;;
Packit c32a2d
		WaitForSingleObjectEx(fifohandle,timer,TRUE);
Packit c32a2d
	}
Packit c32a2d
	debug2("peek %ld bytes, error %ld",ret, err);
Packit c32a2d
	return ret;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
void win32_fifo_close(void)
Packit c32a2d
{
Packit c32a2d
	debug1("Attempting to close handle %p", fifohandle);
Packit c32a2d
	if(fifohandle)
Packit c32a2d
	{
Packit c32a2d
		DisconnectNamedPipe(fifohandle);
Packit c32a2d
		CloseHandle(fifohandle);
Packit c32a2d
	}
Packit c32a2d
	fifohandle = NULL;
Packit c32a2d
}
Packit c32a2d
Packit c32a2d
int win32_fifo_mkfifo(const char *path)
Packit c32a2d
{
Packit c32a2d
	HANDLE ret;
Packit c32a2d
	win32_fifo_close();
Packit c32a2d
#ifdef WANT_WIN32_UNICODE
Packit c32a2d
	wchar_t *str;
Packit c32a2d
	if(win32_utf8_wide(path,&str,NULL) == 0)
Packit c32a2d
	{
Packit c32a2d
		fprintf(stderr,"Cannot get FIFO name, likely out of memory\n");
Packit c32a2d
		return -1;
Packit c32a2d
	}
Packit c32a2d
#if (DEBUG == 1)
Packit c32a2d
	fwprintf(stderr,L"CreateNamedPipeW %ws\n", str);
Packit c32a2d
#endif
Packit c32a2d
	ret = CreateNamedPipeW(str,PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,PIPE_TYPE_BYTE,1,255,255,0,NULL);
Packit c32a2d
	free(str);
Packit c32a2d
#else
Packit c32a2d
#if (DEBUG == 1)
Packit c32a2d
	fprintf(stderr,"CreateNamedPipeA %s\n", path);
Packit c32a2d
#endif
Packit c32a2d
	ret = CreateNamedPipeA(path,PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,PIPE_TYPE_BYTE,1,255,255,0,NULL);
Packit c32a2d
#endif /* WANT_WIN32_UNICODE */
Packit c32a2d
	if(ret == INVALID_HANDLE_VALUE) return -1;
Packit c32a2d
Packit c32a2d
	fifohandle = ret;
Packit c32a2d
	/* Wait for client */
Packit c32a2d
	ConnectNamedPipe(fifohandle,&ov1;;
Packit c32a2d
	WaitForSingleObjectEx(fifohandle,INFINITE,TRUE);
Packit c32a2d
	return 0;
Packit c32a2d
}
Packit c32a2d
#endif /* WANT_WIN32_FIFO */