The Perl Toolchain Summit 2025 Needs You: You can help 🙏 Learn more

/*
+==========================================================+
| |
| ODBC extension for Win32 Perl |
| ----------------------------- |
| |
| by Dave Roth (rothd@infowire.com) |
| |
| version v960522 (hack) |
| |
| Copyright (c) 1996 Dave Roth. All rights reserved. |
| This program is free software; you can redistribute |
| it and/or modify it under the same terms as Perl itself. |
| |
+==========================================================+
based on original code by Dan DeMaggio (dmag@umich.edu)
Use under GNU General Public License or Larry Wall's "Artistic License"
*/
#define WIN32_LEAN_AND_MEAN
#include <stdlib.h>
#include <math.h>
#include <windows.h>
#if defined(__cplusplus)
extern "C" {
#endif
#include <EXTERN.h>
#include "perl.h"
#include "XSub.h"
#include "patchlevel.h"
#if (PATCHLEVEL < 5) && !defined(PL_sv_undef)
# define PL_sv_undef sv_undef
#endif
#if defined(__cplusplus)
}
#endif
#include "cpipe.hpp"
#include "pipe.h"
char gszError[ERROR_TEXT_SIZE];
int giError = 0;
/*----------------------- P E R L F U N C T I O N S -------------------*/
// constant function for exporting NT definitions.
static long constant(char *name)
{
errno = 0;
switch (*name) {
case 'A':
break;
case 'B':
break;
case 'C':
break;
case 'D':
break;
case 'E':
break;
case 'F':
break;
case 'G':
break;
case 'H':
break;
case 'I':
break;
case 'J':
break;
case 'K':
break;
case 'L':
break;
case 'M':
break;
case 'N':
break;
case 'O':
break;
case 'P':
break;
case 'Q':
break;
case 'R':
break;
case 'S':
break;
case 'T':
break;
case 'U':
break;
case 'V':
break;
case 'W':
break;
case 'X':
break;
case 'Y':
break;
case 'Z':
break;
}
errno = EINVAL;
return 0;
not_there:
errno = ENOENT;
return 0;
}
XS(XS_WIN32__Pipe_Constant)
{
dXSARGS;
if (items != 2)
{
croak("Usage: Win23::Pipe::Constant(name, arg)\n");
}
{
STRLEN n_a;
char* name = (char*)SvPV(ST(0),n_a);
ST(0) = sv_newmortal();
sv_setiv(ST(0), constant(name));
}
XSRETURN(1);
}
/*----------------------- M I S C F U N C T I O N S -------------------*/
int Error(int iErrorNum, char *szErrorText){
strncpy((char *)gszError, szErrorText, ERROR_TEXT_SIZE);
gszError[ERROR_TEXT_SIZE] = '\0';
giError = iErrorNum;
return giError;
}
/*------------------- P E R L O D B C F U N C T I O N S ---------------*/
XS(XS_WIN32__Pipe_Create)
{
dXSARGS;
UCHAR *szName = 0;
DWORD dWait = DEFAULT_WAIT_TIME;
CPipe *Pipe = 0;
STRLEN n_a;
if(items != 2){
CROAK("usage: Create(\"$Name\", $TimeToWait);\n");
}
szName = (UCHAR *)SvPV(ST(0), n_a);
dWait = (DWORD)SvIV(ST(1));
PUSHMARK(sp);
if (strlen((const char *)szName) > 255){
Error(ERROR_NAME_TOO_LONG);
}else{
Pipe = new CPipe((char *)szName, dWait);
}
if (Pipe){
if (Pipe->iError){
giError = Pipe->iError;
strcpy(gszError, (const char *)Pipe->szError);
delete Pipe;
Pipe = 0;
}
}
if (Pipe){ // everything is happy
XPUSHs(sv_2mortal(newSViv((long)Pipe)));
}else{
XPUSHs(sv_2mortal(newSViv(0)));
}
PUTBACK;
}
XS(XS_WIN32__Pipe_Close)
{
dXSARGS;
CPipe *Pipe;
if(items != 1){
CROAK("usage: Close($PipeHandle);\n");
}
Pipe = (class CPipe *)SvIV(ST(0));
PUSHMARK(sp);
if (Pipe){
delete Pipe;
}
XPUSHs(sv_2mortal(newSViv(0)));
PUTBACK;
}
XS(XS_WIN32__Pipe_Write)
{
dXSARGS;
CPipe *Pipe = 0;
void *vpData = 0;
int iResult = 0;
STRLEN dDataLen;
if(items != 2){
CROAK("usage: Write($PipeHandle, $Data);\n");
}
Pipe = (class CPipe *)SvIV(ST(0));
vpData = (void *)SvPV(ST(1), dDataLen);
PUSHMARK(sp);
if (Pipe){
iResult = Pipe->Write((void *)vpData, (DWORD)dDataLen);
}
XPUSHs(sv_2mortal(newSViv(iResult)));
PUTBACK;
}
XS(XS_WIN32__Pipe_Read)
{
dXSARGS;
CPipe *Pipe = 0;
int iFlag = 1;
DWORD dLen = 0;
void *vpData = 0;
if(items != 1){
CROAK("usage: Read($PipeHandle);\n");
}
Pipe = (class CPipe *)SvIV(ST(0));
PUSHMARK(sp);
if (Pipe){
while(iFlag){
vpData = Pipe->Read(&dLen);
iFlag = 0;
// If we have more data to read then for God's sake, do it!
// I don't know if this will work ... it would return an
// array. This may not be good. Hmmmm.
if(!vpData && GetLastError() == ERROR_MORE_DATA){
iFlag = 1;
}
if(dLen){
XPUSHs(sv_2mortal(newSVpv((char *)vpData, dLen)));
}else{
sv_setsv(ST(0), (SV*) &PL_sv_undef);
}
}
}
PUTBACK;
}
XS(XS_WIN32__Pipe_Connect)
{
dXSARGS;
CPipe *Pipe;
int iResult = 0;
if(items != 1){
CROAK("usage: Connect($PipeHandle);\n");
}
Pipe = (class CPipe *)SvIV(ST(0));
PUSHMARK(sp);
if (Pipe){
iResult = Pipe->Connect();
}
XPUSHs(sv_2mortal(newSViv((long)iResult)));
PUTBACK;
}
XS(XS_WIN32__Pipe_Disconnect)
{
dXSARGS;
CPipe *Pipe;
int iResult = 0;
int iPurge = 0;
if(items > 0 && items < 3){
CROAK("usage: Disconnect($PipeHandle [, $iPurge]);\n");
}
Pipe = (class CPipe *)SvIV(ST(0));
if (items == 2){
iPurge = (int) SvIV(ST(1));
}
PUSHMARK(sp);
if (Pipe){
iResult = Pipe->Disconnect(iPurge);
}
XPUSHs(sv_2mortal(newSViv((long)iResult)));
PUTBACK;
}
XS(XS_WIN32__Pipe_ResizeBuffer)
{
dXSARGS;
CPipe *Pipe = 0;
DWORD dResult = 0;
DWORD dSize;
if(items != 2){
CROAK("usage: ResizeBuffer($PipeHandle, $Size);\n");
}
Pipe = (class CPipe *)SvIV(ST(0));
dSize = (DWORD)SvIV(ST(1));
PUSHMARK(sp);
if (Pipe){
dResult = Pipe->ResizeBuffer(dSize);
}
XPUSHs(sv_2mortal(newSViv((long)dResult)));
PUTBACK;
}
XS(XS_WIN32__Pipe_BufferSize)
{
dXSARGS;
CPipe *Pipe = 0;
DWORD dResult = 0;
if(items != 1){
CROAK("usage: BufferSize($PipeHandle);\n");
}
Pipe = (class CPipe *)SvIV(ST(0));
PUSHMARK(sp);
if (Pipe){
dResult = Pipe->BufferSize();
}
XPUSHs(sv_2mortal(newSViv((long)dResult)));
PUTBACK;
}
XS(XS_WIN32__Pipe_Error)
{
dXSARGS;
CPipe *Pipe = 0;
int iResult = 0;
char *szError = 0;
int iError = 0;
if(items > 1){
CROAK("usage: Error([$PipeHandle]);\n");
}
if (items == 1){
Pipe = (class CPipe *)SvIV(ST(0));
}
PUSHMARK(sp);
if (Pipe){
iError = Pipe->iError;
szError = (char *)Pipe->szError;
}else{
iError = giError;
szError = gszError;
}
XPUSHs(sv_2mortal(newSViv((long)iError)));
XPUSHs(sv_2mortal(newSVpv((char *)szError, strlen(szError))));
PUTBACK;
}
XS(XS_WIN32__Pipe_Info)
{
dXSARGS;
if(items > 0){
CROAK("usage: ($ExtName, $Version, $Date, $Author, $CompileDate, $Credits) = Info()\n");
}
PUSHMARK(sp);
XPUSHs(sv_2mortal(newSVpv(VERNAME, strlen(VERNAME))));
XPUSHs(sv_2mortal(newSVpv(VERSION, strlen(VERSION))));
XPUSHs(sv_2mortal(newSVpv(VERDATE, strlen(VERDATE))));
XPUSHs(sv_2mortal(newSVpv(VERAUTH, strlen(VERAUTH))));
XPUSHs(sv_2mortal(newSVpv(__DATE__, strlen(__DATE__))));
XPUSHs(sv_2mortal(newSVpv(__TIME__, strlen(__TIME__))));
XPUSHs(sv_2mortal(newSVpv(VERCRED, strlen(VERCRED))));
PUTBACK;
}
#if defined(__cplusplus)
extern "C"
#endif
XS(boot_Win32__Pipe)
{
dXSARGS;
char* file = __FILE__;
int i;
giError = 0;
memset((void *)gszError, 0, ERROR_TEXT_SIZE);
newXS("Win32::Pipe::constant", XS_WIN32__Pipe_Constant, file);
newXS("Win32::Pipe::PipeCreate", XS_WIN32__Pipe_Create, file);
newXS("Win32::Pipe::PipeClose", XS_WIN32__Pipe_Close, file);
newXS("Win32::Pipe::PipeWrite", XS_WIN32__Pipe_Write, file);
newXS("Win32::Pipe::PipeRead", XS_WIN32__Pipe_Read, file);
newXS("Win32::Pipe::PipeConnect", XS_WIN32__Pipe_Connect, file);
newXS("Win32::Pipe::PipeDisconnect", XS_WIN32__Pipe_Disconnect, file);
newXS("Win32::Pipe::PipeError", XS_WIN32__Pipe_Error, file);
newXS("Win32::Pipe::PipeResizeBuffer", XS_WIN32__Pipe_ResizeBuffer, file);
newXS("Win32::Pipe::PipeBufferSize", XS_WIN32__Pipe_BufferSize, file);
newXS("Win32::Pipe::Info", XS_WIN32__Pipe_Info, file);
XSRETURN_YES;
}