Windows API

Blitz3D Forums/Blitz3D Programming/Windows API

xtremegamr(Posted 2009) [#1]
I'm trying to use the CreatePipe() function in the Windows API to create a pipe between 2 applications.

Here's the code I'm using:
readpipe=CreateBank(5)
writepipe=CreateBank(5)

r=api_CreatePipe( readpipe, writepipe, Null, 5 )
If r=0 Then Print api_GetLastError()


I keep getting a MAV error on this line, though:
r=api_CreatePipe( readpipe, writepipe, Null, 5 )


Does anyone know what I'm doing wrong?


Guy Fawkes(Posted 2009) [#2]
perhaps this will help?

http://msdn.microsoft.com/en-us/library/aa365152(VS.85).aspx


xtremegamr(Posted 2009) [#3]
Oh yeah...I forgot about MSDN... :)

It says that the first 2 parameters of CreatePipe() need to be pointers...but since there are no pointers in Blitz, what do I do?


Guy Fawkes(Posted 2009) [#4]
u locate the pointer value (IN HEX) from online.

then..

u use them like this:

Const nul = $0000 ;(0x00)
Const mypointer = $0001 ;(0x01)

r=api_CreatePipe( readpipe, writepipe, nul, ,mypointer )
btw. ur getting a mav because Null is a function wrapped into blitz3d.

so use "nul" instead ;)


xtremegamr(Posted 2009) [#5]
u locate the pointer value (IN HEX) from online.


?? I'm confused.

btw. ur getting a mav because Null is a function wrapped into blitz3d.

Ohh...so I can't use Null, I have to use $0000...


Guy Fawkes(Posted 2009) [#6]
well. sorta.

the constant "nul" is in PLACE of "Null" as null in any other program language stands for nothing, so u would use const nul = $0000

u go on google and search for which pointer ur looking for. THEN. u locate the VALUE on google, of that pointer.

you then put the 2 together:

Const mypointer = $0001 ;(example) (0x01)

then u finally use it in the api call:

r=api_CreatePipe( readpipe, writepipe, nul, mypointer)

why do u use readpipe, writepipe, nul, mypointer? because u defined what the pointer should be, and what nul should be ;)


Guy Fawkes(Posted 2009) [#7]
make SURE the pointer is right. otherwise, it will crash or give u a mav. ;) and make sure "readpipe" & "writepipe" r correct too, or the same thing will happen

btw, $ stands for hex.

simple as that.

and const defines a constant followed by an integer or hex ($) value. :)


xtremegamr(Posted 2009) [#8]

u go on google and search for which pointer ur looking for. THEN. u locate the VALUE on google, of that pointer.



I'm still confused. Isn't a pointer a variable that contains a position in memory? So how would I search it on Google?


Guy Fawkes(Posted 2009) [#9]
well 1st. whats the name of the pointer? u must know what the name of the pointer u want is. and what it does.

THEN u take the name of the pointer and look it up like this man:

mypointer hex value

:)


xtremegamr(Posted 2009) [#10]
whats the name of the pointer?

What do you mean? Can't I name it whatever I want?

In C++, a pointer is just like a variable, except it holds a position in memory. Since CreatePipe() needs pointers to variables, this basically means that I need to know where my variables are stored in memory.

You're talking about finding the name, then searching it on Google, and now, I'm SO confused... :)


Warner(Posted 2009) [#11]
The confusion is between the terms 'pointer' and 'flag'. A flag value can be found online. You could use a bank as a pointer. I read user types can also be used, however I only used banks.
bank = createbank(8)
api_gettwointegersfromdll (bank)
print pokeint(bank, 0)
print pokeint(bank, 4) ;<--since integer is 4 bytes.



Guy Fawkes(Posted 2009) [#12]
yes. u can name it whatever u want, but its better to name it the original pointer. like "hWnd", because i GUARANTEE if u make a library of const, ull get confused :)

also, ull need to know the original name of the pointer ONLY to be able to find the hex value of it on google. What u name it in blitz is up to u, but to find the pointer, ull need the original name of the pointer :)


xtremegamr(Posted 2009) [#13]
OK, so instead of supplying pointers to CreatePipe(), I should supply banks...

*checks code*

But that's what I've been doing, and I'm still getting MAV's.

The confusion is between the terms 'pointer' and 'flag'.

Ohhh...so what DarkShadowWing meant was that I needed to find the flag value online! Lol, we were talking about 2 different things!


Guy Fawkes(Posted 2009) [#14]
yea. thats the word. sorry. im half awake. lol. and my program is giving me PLENTY of problems of my own.. :P

but its always good to help somebody too, so i can learn how to do it too :P

anyway. yes, u look up the flag value online, and use it like this:

Const WM_PAINT = $000A

mywin = api_CreateWindow(systemproperty("ApphWnd", 0, 0, graphicswidth()/4, graphicsheight(), WM_PAINT)

:)


xtremegamr(Posted 2009) [#15]
OK, now that that's out of the way, we're back to my original problem: this code...

readpipe=CreateBank(4)
writepipe=CreateBank(4)
;
Const nul=$0000

;
r=api_CreatePipe( readpipe, writepipe, nul, 5 )
If r=0 Then Print api_GetLastError()


...is giving me MAV's on this line:
r=api_CreatePipe( readpipe, writepipe, nul, 5 )


I hate to sound ungrateful (I really do appreciate you guys trying to help me), but I'm still as lost as before.


Guy Fawkes(Posted 2009) [#16]
whats the '5' for?

readpipe=CreateBank(4)
writepipe=CreateBank(4)
;
Const nul=$0000
Const WM_PAINT = $000A ;REPLACE THIS LINE WITH Const MY_VAR = $flag hex of utr variable

;
r=api_CreatePipe( readpipe, writepipe, nul, POINTER GOES HERE)
If r=0 Then Print api_GetLastError()

:)


Guy Fawkes(Posted 2009) [#17]
its crashing cuz ur using 5.

5 may be an inappropriate value..

instead of "5", u should use the hex. because $0005 doesnt mean in integer form it is still "5". it means it's "6". :)


Warner(Posted 2009) [#18]
I suppose it is the banksize that is not correct:
readpipe=CreateBank(255)
writepipe=CreateBank(255)

r=api_CreatePipe( readpipe, writepipe, 0, 0 )
If r=0 Then Print api_GetLastError()



Guy Fawkes(Posted 2009) [#19]
remember, 0 DOES count in hex. :) 0 = 1, 1 = 2.


xtremegamr(Posted 2009) [#20]
whats the '5' for?


According to MSDN:

Parameters

hReadPipe [out]
A pointer to a variable that receives the read handle for the pipe.

hWritePipe [out]
A pointer to a variable that receives the write handle for the pipe.

lpPipeAttributes [in, optional]
A pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If lpPipeAttributes is NULL, the handle cannot be inherited.

The lpSecurityDescriptor member of the structure specifies a security descriptor for the new pipe. If lpPipeAttributes is NULL, the pipe gets a default security descriptor. The ACLs in the default security descriptor for a pipe come from the primary or impersonation token of the creator.

nSize [in]
The size of the buffer for the pipe, in bytes. The size is only a suggestion; the system uses the value to calculate an appropriate buffering mechanism. If this parameter is zero, the system uses the default buffer size.




So the last parameter (nSize) is the size of the buffer for the pipe. I just picked a random integer and hoped for the best. :)

I tried using '$0005' instead of '5', and even '$0255' and '$1234', but I still get MAV's.

@Warner:
I tried changing the bank sizes, but it still doesn't work.


Guy Fawkes(Posted 2009) [#21]
when all else fails, find a VB code (Visual Basic) that shows how to use "CreatePipe", and slowly convert it to blitz ;)


Guy Fawkes(Posted 2009) [#22]
take a look @ this code:

static int	CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *
processInfo);
static char *pipe_read_line(char *cmd, char *line, int maxsize);

int
main (int argc, char * argv[])
{
char		*restrict_env;
char		line[100];
char		cmd[1024];
HANDLE		ProcessPToken;

/* Say hello and bail out of required */
fprintf(stdout, "Hello from: %s\n", argv[0]);
if (argc > 1 && !strcmp(argv[1], "-x"))
return 0;


/*
* Before we execute another program, make sure that we are running with a
* restricted token. If not, re-execute ourselves with one.
*/

if ((restrict_env = getenv("PG_RESTRICT_EXEC")) == NULL
|| strcmp(restrict_env, "1") != 0)
{
PROCESS_INFORMATION pi;

ZeroMemory(&#960;, sizeof(pi));

putenv("PG_RESTRICT_EXEC=1");
fprintf(stdout, "Re-execing with restricted token...\n");

if (!CreateRestrictedProcess(argv[0], &#960;))
{
fprintf(stderr, "Failed to re-exec with restricted token: %lu.\n",
GetLastError());
}
else
{
/*
* Successfully re-execed. Now wait for child process to capture
* exitcode.
*/
DWORD		x;

CloseHandle(pi.hThread);
WaitForSingleObject(pi.hProcess, INFINITE);

if (!GetExitCodeProcess(pi.hProcess, &x))
{
fprintf(stderr, "Failed to get exit code from subprocess: %lu\n",
GetLastError());
exit(1);
}
exit(x);
}
}

fprintf(stdout, "Starting child process...\n");
_snprintf(cmd, sizeof(cmd), "%s -x", argv[0]);
if (pipe_read_line(cmd, line, sizeof(line)))
fprintf(stdout, "Output from other exec: %s\n", line);

return 0;
}

/*
* Create a restricted token and execute the specified process with it.
*
* Returns 0 on failure, non-zero on success, same as CreateProcess().
*
* On NT4, or any other system not containing the required functions, will
* NOT execute anything.
*/

typedef		BOOL(WINAPI * __CreateRestrictedToken) (HANDLE, DWORD, DWORD,
PSID_AND_ATTRIBUTES, DWORD, PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES,
PHANDLE);

static int
CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION * processInfo)
{
BOOL		b;
STARTUPINFO si;
HANDLE		origToken;
HANDLE		restrictedToken;
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
SID_AND_ATTRIBUTES dropSids[2];
__CreateRestrictedToken _CreateRestrictedToken = NULL;
HMODULE		Advapi32Handle;

ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);

Advapi32Handle = LoadLibrary("ADVAPI32.DLL");
if (Advapi32Handle != NULL)
{
_CreateRestrictedToken = (__CreateRestrictedToken)
GetProcAddress(Advapi32Handle, "CreateRestrictedToken");
}

if (_CreateRestrictedToken == NULL)
{
fprintf(stderr, "WARNING: cannot create restricted tokens on this
platform\n");
if (Advapi32Handle != NULL)
FreeLibrary(Advapi32Handle);
return 0;
}

/* Open the current token to use as a base for the restricted one */
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &origToken))
{
fprintf(stderr, "Failed to open process token: %lu\n", GetLastError());
return 0;
}

/* Allocate list of SIDs to remove */
ZeroMemory(&dropSids, sizeof(dropSids));
if (!AllocateAndInitializeSid(&NtAuthority, 2,
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
0, &dropSids[0].Sid) ||
!AllocateAndInitializeSid(&NtAuthority, 2,
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
0, &dropSids[1].Sid))
{
fprintf(stderr, "Failed to allocate SIDs: %lu\n", GetLastError());
return 0;
}

b = _CreateRestrictedToken(origToken,
DISABLE_MAX_PRIVILEGE,
sizeof(dropSids) / sizeof(dropSids[0]),
dropSids,
0, NULL,
0, NULL,
&restrictedToken);

FreeSid(dropSids[1].Sid);
FreeSid(dropSids[0].Sid);
CloseHandle(origToken);
FreeLibrary(Advapi32Handle);

if (!b)
{
fprintf(stderr, "Failed to create restricted token: %lu\n", GetLastError());
return 0;
}

return CreateProcessAsUser(restrictedToken, NULL, cmd, NULL, NULL, TRUE, 0,
NULL, NULL, &si, processInfo);
}

/*
* The runtime library's popen() on win32 does not work when being
* called from a service when running on windows <= 2000, because
* there is no stdin/stdout/stderr.
*
* Executing a command in a pipe and reading the first line from it
* is all we need.
*/
static char *
pipe_read_line(char *cmd, char *line, int maxsize)
{
SECURITY_ATTRIBUTES sattr;
HANDLE		childstdoutrd,
childstdoutwr,
childstdoutrddup;
PROCESS_INFORMATION pi;
STARTUPINFO si;
char	   *retval = NULL;

sattr.nLength = sizeof(SECURITY_ATTRIBUTES);
sattr.bInheritHandle = TRUE;
sattr.lpSecurityDescriptor = NULL;

{
int x = 0;
while (!x)
{
Sleep(100);
}
}

if (!CreatePipe(&childstdoutrd, &childstdoutwr, &sattr, 0))
{
fprintf(stderr, "CreatePipe failed with error code %d\n", GetLastError());
return NULL;
}

if (!DuplicateHandle(GetCurrentProcess(),
childstdoutrd,
GetCurrentProcess(),
&childstdoutrddup,
0,
FALSE,
DUPLICATE_SAME_ACCESS))
{
CloseHandle(childstdoutrd);
CloseHandle(childstdoutwr);
return NULL;
}

CloseHandle(childstdoutrd);

ZeroMemory(&#960;, sizeof(pi));
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdError = childstdoutwr;
si.hStdOutput = childstdoutwr;
si.hStdInput = INVALID_HANDLE_VALUE;

if (CreateProcess(NULL,
cmd,
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&si,
&#960;))
{
/* Successfully started the process */
char	   *lineptr;

ZeroMemory(line, maxsize);

/* Try to read at least one line from the pipe */
/* This may require more than one wait/read attempt */
for (lineptr = line; lineptr < line + maxsize - 1;)
{
DWORD		bytesread = 0;

/* Let's see if we can read */
if (WaitForSingleObject(childstdoutrddup, 10000) != WAIT_OBJECT_0)
break;			/* Timeout, but perhaps we got a line already */

if (!ReadFile(childstdoutrddup, lineptr, maxsize - (lineptr - line),
&bytesread, NULL))
break;			/* Error, but perhaps we got a line already */

lineptr += strlen(lineptr);

if (!bytesread)
break;			/* EOF */

if (strchr(line, '\n'))
break;			/* One or more lines read */
}

if (lineptr != line)
{
/* OK, we read some data */
size_t			len;

/* If we got more than one line, cut off after the first \n */
lineptr = strchr(line, '\n');
if (lineptr)
*(lineptr + 1) = '\0';

len = strlen(line);

/*
* If EOL is \r\n, convert to just \n. Because stdout is a
* text-mode stream, the \n output by the child process is
* received as \r\n, so we convert it to \n.  The server main.c
* sets setvbuf(stdout, NULL, _IONBF, 0) which has the effect of
* disabling \n to \r\n expansion for stdout.
*/
if (len >= 2 && line[len - 2] == '\r' && line[len - 1] == '\n')
{
line[len - 2] = '\n';
line[len - 1] = '\0';
len--;
}

/*
* We emulate fgets() behaviour. So if there is no newline at the
* end, we add one...
*/
if (len == 0 || line[len - 1] != '\n')
strcat(line, "\n");

retval = line;
}

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}

CloseHandle(childstdoutwr);
CloseHandle(childstdoutrddup);

return retval;
}


i found it online..

try using "0" in place of "5" or "$0005"

hehe :)


xtremegamr(Posted 2009) [#23]
Thx!

Stupid question, though: Is that C++ code, or VB?


Guy Fawkes(Posted 2009) [#24]
It worked? :)

And that I think is c++ :)


jfk EO-11110(Posted 2009) [#25]
Warner: pokeint(bank, 0) guess you meant peekint, right?

DarkShadowWind: since when is in hex 0=1, 1=2 ? And what's the name of those pills and whrere can I get them ?
0=0
1=1
....
9=9
A=10
B=11
...
F=15
10=16
...
(hope you don't mind, but what would you expect ;) )
I guess you confused this with the fact that when you say DIM A(10) then there's 11 A's, A zero to A ten.

However, just a sidenote: depending on if you want to hand over to the api function a variable or a bank handle, you need to use the right postfix (in the decls file). Example: Giving the function a bank handle will allow the function to write some data to it. So when the function needs a pointer to write something to, use a bank handle, like "destination*" (note the asterisk). If the function simply needs some sort of parameter then omit the postfix, eg. "Length". In Blitz you will then simple use a variable containing the wanted value there.

in decls:
.lib "kernel32.dll"
RtlMoveMemory2%(Destination*,Source,Length) : "RtlMoveMemory"

in blitz:
RtlMoveMemory2(mybank,x,w)


Note: if you declare a function multiple times with various names (eg. because you want to be able to use various sets of variables: one time banks, an other time variables...) then you have to declare the orignal function name at the end of the line, as seen here. ( : "RtlMoveMemory" )

BTW i had only a quick view, but it seems to be yu can't use them with writepipe and readpipe only, but you have to
use CreatePipe and Closehandle as well. Handles are used. (just like a file handle)


xtremegamr(Posted 2009) [#26]
I found the problem! It wasn't my code at all! It was my .decls file!

In the .decls, the entry was:
api_CreatePipe% (phReadPipe%, phWritePipe%, lpPipeAttributes*, nSize%) : "CreatePipe"


...when it should have been:
api_CreatePipe% (phReadPipe*, phWritePipe*, lpPipeAttributes%, nSize%) : "CreatePipe",


Thanks for the help, guys! I feel like such an idiot now! :)


Guy Fawkes(Posted 2009) [#27]
heh. thats what we're here for man.

np man


Warner(Posted 2009) [#28]
Damn, mixed up my peeks and pokes again. No wonder I didn't pass my QB45 exam. :(