Windows API
Blitz3D Forums/Blitz3D Programming/Windows API
| ||
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? |
| ||
perhaps this will help? http://msdn.microsoft.com/en-us/library/aa365152(VS.85).aspx |
| ||
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? |
| ||
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 ;) |
| ||
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... |
| ||
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 ;) |
| ||
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. :) |
| ||
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? |
| ||
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 :) |
| ||
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... :) |
| ||
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. |
| ||
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 :) |
| ||
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! |
| ||
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) :) |
| ||
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. |
| ||
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() :) |
| ||
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". :) |
| ||
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() |
| ||
remember, 0 DOES count in hex. :) 0 = 1, 1 = 2. |
| ||
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. |
| ||
when all else fails, find a VB code (Visual Basic) that shows how to use "CreatePipe", and slowly convert it to blitz ;) |
| ||
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(π, sizeof(pi)); putenv("PG_RESTRICT_EXEC=1"); fprintf(stdout, "Re-execing with restricted token...\n"); if (!CreateRestrictedProcess(argv[0], π)) { 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(π, 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, π)) { /* 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 :) |
| ||
Thx! Stupid question, though: Is that C++ code, or VB? |
| ||
It worked? :) And that I think is c++ :) |
| ||
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) |
| ||
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! :) |
| ||
heh. thats what we're here for man. np man |
| ||
Damn, mixed up my peeks and pokes again. No wonder I didn't pass my QB45 exam. :( |