NDIS_STATUS HvlQueueNotification( PHVL pHvl, PVOID pvNotif ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PHVL_NOTIFICATION pHvlNotif = NULL; PNOTIFICATION_DATA_HEADER pHdr = (PNOTIFICATION_DATA_HEADER)pvNotif; PVOID pVNicNotif = NULL; ASSERT(HvlIsLocked(pHvl)); do { ndisStatus = ALLOC_MEM(pHvl->MiniportAdapterHandle, sizeof(HVL_NOTIFICATION), &pHvlNotif); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("Failed to allocate memory for a HVL notification\n")); break; } ndisStatus = ALLOC_MEM(pHvl->MiniportAdapterHandle, pHdr->Size, &pVNicNotif); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("Failed to allocate memory for notification\n")); break; } NdisMoveMemory(pVNicNotif , pvNotif, pHdr->Size); pHvlNotif->pvNotif = pVNicNotif; InsertTailList(&pHvl->NotificationsQueue, &pHvlNotif->Link); } while (FALSE); if (NDIS_FAILURE(ndisStatus)) { HvlFreeNotification(pHvlNotif); } return ndisStatus; }
NDIS_STATUS HvlQueuePendingOperation( _In_ PHVL pHvl, _In_ HVL_PENDING_OP_TYPE OpType, _In_ PVOID pvOpData, _In_ BOOLEAN fPnpOperation ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PHVL_PENDING_OP pPendingOp = NULL; do { if (fPnpOperation) { ASSERT(pHvl->PnpPendingOp.Link.Blink == NULL && pHvl->PnpPendingOp.Link.Flink == NULL); pPendingOp = &pHvl->PnpPendingOp; } else { ndisStatus = ALLOC_MEM(pHvl->MiniportAdapterHandle, sizeof(HVL_PENDING_OP), &pPendingOp); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("Failed to allocate memory for a new pending operation")); break; } pPendingOp->Type = OpType; pPendingOp->pvOpData= pvOpData; } InsertTailList(&pHvl->PendingOpQueue, &pPendingOp->Link); } while (FALSE); if (NDIS_STATUS_SUCCESS != ndisStatus) { if (pPendingOp) { if (fPnpOperation) { HvlInitPreAllocatedOp(pHvl); } else { HvlDeletePendingOperation(pHvl, pPendingOp); } } } return ndisStatus; }
NDIS_STATUS VNicQueuePendingOperation( _In_ PVNIC pVNic, _In_ PENDING_OP_TYPE OpType, _In_opt_ PVOID pvOpData, _In_ BOOLEAN fPnPOperation ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PPENDING_OP pPendingOp = NULL; do { if (fPnPOperation) { ASSERT(pVNic->PnpPendingOp.Link.Blink == NULL && pVNic->PnpPendingOp.Link.Flink == NULL); pPendingOp = &pVNic->PnpPendingOp; } else { ndisStatus = ALLOC_MEM(pVNic->MiniportAdapterHandle, sizeof(PENDING_OP), &pPendingOp); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("VNic(%d): Failed to allocate memory for a new pending operation", VNIC_PORT_NO)); break; } pPendingOp->Type = OpType; pPendingOp->pvOpData= pvOpData; } InsertTailList(&pVNic->PendingOpQueue, &pPendingOp->Link); } while (FALSE); if (NDIS_STATUS_SUCCESS != ndisStatus) { if (!fPnPOperation && pPendingOp) { VNicDeletePendingOperation(pVNic, pPendingOp); } } return ndisStatus; }
NDIS_STATUS VNicAllocateChSwReq( _In_ PVNIC pVNic, _In_ ULONG ulChannel, _In_ ULONG ulPhyId, _In_ BOOLEAN fSwitchPhy, _In_ PORT11_GENERIC_CALLBACK_FUNC pfnCompletionHandler, PCH_SWITCH_REQ *ppChSwReq ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PCH_SWITCH_REQ pChSwReq = NULL; do { *ppChSwReq = NULL; ndisStatus = ALLOC_MEM(pVNic->MiniportAdapterHandle, sizeof(CH_SWITCH_REQ), &pChSwReq); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("VNic(%d): Failed to allocate memory for a new channel switch request\n", VNIC_PORT_NO)); break; } pChSwReq->ulChannel = ulChannel; pChSwReq->ulPhyId = ulPhyId; pChSwReq->fSwitchPhy = fSwitchPhy; pChSwReq->pfnCompletionHandler = pfnCompletionHandler; *ppChSwReq = pChSwReq; } while (FALSE); if (NDIS_STATUS_SUCCESS != ndisStatus) { if (pChSwReq) { FREE_MEM(pChSwReq); } } return ndisStatus; }
NDIS_STATUS VNicQueueStopBSSRequest( _In_ PVNIC pVNic, _In_ PORT11_GENERIC_CALLBACK_FUNC CompletionHandler ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PSTOP_BSS_REQ pStopBssReq = NULL; ASSERT(VNicIsLocked(pVNic)); do { ndisStatus = ALLOC_MEM(pVNic->MiniportAdapterHandle, sizeof(STOP_BSS_REQ), &pStopBssReq); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("VNic(%d): Failed to allocate memory for a new stop BSS request\n", VNIC_PORT_NO)); break; } pStopBssReq->CompletionHandler = CompletionHandler; ndisStatus = VNicQueuePendingOperation(pVNic, PENDING_OP_STOP_BSS_REQ, pStopBssReq, FALSE); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("VNic(%d): VNicQueuePendingOperation failed 0x%x\n", VNIC_PORT_NO, ndisStatus)); break; } MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): Queued a stop BSS request\n", VNIC_PORT_NO)); } while (FALSE); if (NDIS_STATUS_SUCCESS != ndisStatus) { if (pStopBssReq) { FREE_MEM(pStopBssReq); } } return ndisStatus; }
PHTTP_IO_CONTEXT GetIOContext() { PHTTP_IO_CONTEXT pContext; PLOOKASIDE pCacheEntry; PSLIST_ENTRY pEntry; pCacheEntry = &IoContextCacheList[IO_CONTEXT_PROC_INDEX]; pEntry = InterlockedPopEntrySList(&pCacheEntry->Header); if(pEntry != NULL) { // Return address of the containing structure. pContext = CONTAINING_RECORD(pEntry, HTTP_IO_CONTEXT, LookAsideEntry); } else { pContext = (PHTTP_IO_CONTEXT)ALLOC_MEM(sizeof(HTTP_IO_CONTEXT)); } ZeroMemory(pContext, sizeof(HTTP_IO_CONTEXT)); return pContext; }
NDIS_STATUS VNicAllocateResetReq( _In_ PVNIC pVNic, _In_ PVNIC_REQ pReq, _In_ PDOT11_RESET_REQUEST pDot11ResetReq, PRESET_REQ *ppResetReq ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PRESET_REQ pResetReq = NULL; do { *ppResetReq = NULL; ndisStatus = ALLOC_MEM(pVNic->MiniportAdapterHandle, sizeof(RESET_REQ), &pResetReq); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("VNic(%d): Failed to allocate memory for a new dot11 reset request\n", VNIC_PORT_NO)); break; } pResetReq->pReq = pReq; pResetReq->pDot11ResetReq = pDot11ResetReq; *ppResetReq = pResetReq; } while (FALSE); if (NDIS_STATUS_SUCCESS != ndisStatus) { if (pResetReq) { FREE_MEM(pResetReq); } } return ndisStatus; }
NDIS_STATUS VNicAllocateExAccessReq( _In_ PVNIC pVNic, _In_ PORT11_GENERIC_CALLBACK_FUNC pCallbkFn, _In_ PVOID pvCtx, _In_ BOOLEAN fPnPOperation, _Out_ PVNIC_EX_ACCESS_REQ *ppExReq ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PVNIC_EX_ACCESS_REQ pExReq = NULL; do { if (fPnPOperation) { pExReq = pVNic->pPnpOpExReq; } else { ndisStatus = ALLOC_MEM(pVNic->MiniportAdapterHandle, sizeof(VNIC_EX_ACCESS_REQ), &pExReq); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("VNic(%d): Failed to allocate memory for a new exclusive access request\n", VNIC_PORT_NO)); break; } } pExReq->CallbkFn = pCallbkFn; pExReq->pvCtx = pvCtx; } while (FALSE); *ppExReq = pExReq; return ndisStatus; }
DWORD CreateHttpListener( OUT PHTTP_LISTENER* httpListener ) { ULONG result; PHTTP_LISTENER _listener = (PHTTP_LISTENER)ALLOC_MEM(sizeof(HTTP_LISTENER)); ZeroMemory(_listener, sizeof(HTTP_LISTENER)); (*httpListener) = _listener; _listener->hRequestQueue = NULL; _listener->RequestQueueLength = 5000; // Default request queue length; _listener->errorCode = 0; _listener->urls = NULL; _listener->pthreadPoolIO = NULL; _listener->State = HTTP_LISTENER_STATE_FAULTED; _listener->stats = (PLISTENER_STATS)_aligned_malloc(sizeof(LISTENER_STATS),MEMORY_ALLOCATION_ALIGNMENT); HTTPAPI_VERSION HttpApiVersion = HTTPAPI_VERSION_2; // // Initialize HTTP APIs. // result = HttpInitialize( HttpApiVersion, HTTP_INITIALIZE_SERVER, // Flags NULL // Reserved ); if (result != NO_ERROR) { DEBUG_ASSERT(false); LOG_ERROR(L"\nHttpInitialize failed with %lu", result); } if(result == NO_ERROR) { result = HttpCreateServerSession(HttpApiVersion, &_listener->SessionId, NULL); if(result) { LOG_ERROR(L"\nHttpCreateServerSession failed with %lu", result); } } if(result == NO_ERROR) { result = HttpCreateRequestQueue(HttpApiVersion, NULL, NULL, 0, &_listener->hRequestQueue); if(result) { LOG_ERROR(L"\nHttpCreateRequestQueue failed with %lu", result); } } if(result == NO_ERROR) { result = HttpSetRequestQueueProperty(_listener->hRequestQueue, HttpServerQueueLengthProperty, &_listener->RequestQueueLength, sizeof(_listener->RequestQueueLength), NULL, NULL); if(result) { LOG_ERROR(L"\nHttpSetRequestQueueProperty failed with %lu", result); } } if(result == NO_ERROR) { if(SetFileCompletionNotificationModes(_listener->hRequestQueue, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS | FILE_SKIP_SET_EVENT_ON_HANDLE) == FALSE) { result = GetLastError(); } } if(result == NO_ERROR) { result = HttpListenerInitializeThreadPool(_listener); } if(result == NO_ERROR) { _listener->pthreadPoolIO = CreateThreadpoolIo(_listener->hRequestQueue, HttpListenerDemuxer, (void*)_listener, &_listener->tpEnvironment); } InitializeIOContextCache(); InitializeHttpInputQueue(_listener); _listener->errorCode = result; return _listener->errorCode; }
/* * processRPCCall() is called after some validations. The assumption is that * the request is an HTTP post of content-type text/xml with a content-length * that is less than the maximum the library can handle. * * The caller should check the error status, and if the error was other than * a network type, respond back to the client to let them know the call failed. */ void processRPCCall( xmlrpc_env * const envP, IN HANDLE hReqQueue, IN PHTTP_REQUEST pRequest ) { HTTP_RESPONSE response; DWORD result; DWORD bytesSent; PUCHAR pEntityBuffer; ULONG EntityBufferLength; ULONG BytesRead; #define MAX_ULONG_STR ((ULONG) sizeof("4294967295")) CHAR szContentLength[MAX_ULONG_STR]; CHAR szServerHeader[20]; HTTP_DATA_CHUNK dataChunk; ULONG TotalBytesRead = 0; xmlrpc_mem_block * body; xmlrpc_mem_block * output; BytesRead = 0; body = NULL; output = NULL; // Allocate some space for an entity buffer. EntityBufferLength = 2048; pEntityBuffer = (PUCHAR) ALLOC_MEM( EntityBufferLength ); if (pEntityBuffer == NULL) { xmlrpc_faultf(envP, "Out of Memory"); goto Done; } // NOTE: If we had passed the HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY // flag with HttpReceiveHttpRequest(), the entity would have // been a part of HTTP_REQUEST (using the pEntityChunks field). // Since we have not passed that flag, we can be assured that // there are no entity bodies in HTTP_REQUEST. if(pRequest->Flags & HTTP_REQUEST_FLAG_MORE_ENTITY_BODY_EXISTS) { //Allocate some space for an XMLRPC memory block. body = xmlrpc_mem_block_new(envP, 0); if (envP->fault_occurred) goto Done; // The entity body can be sent over multiple calls. Let's collect all // of these in a buffer and send the buffer to the xmlrpc-c library do { // Read the entity chunk from the request. BytesRead = 0; result = HttpReceiveRequestEntityBody( hReqQueue, pRequest->RequestId, 0, pEntityBuffer, EntityBufferLength, &BytesRead, NULL ); switch(result) { case NO_ERROR: if(BytesRead != 0) { XMLRPC_MEMBLOCK_APPEND(char, envP, body, pEntityBuffer, BytesRead); if(envP->fault_occurred) goto Done; } break; case ERROR_HANDLE_EOF: // We have read the last request entity body. We can now // process the suppossed XMLRPC data. if(BytesRead != 0) { XMLRPC_MEMBLOCK_APPEND(char, envP, body, pEntityBuffer, BytesRead); if(envP->fault_occurred) goto Done; } // We will send the response over multiple calls. // This is achieved by passing the // HTTP_SEND_RESPONSE_FLAG_MORE_DATA flag. // NOTE: Since we are accumulating the TotalBytesRead in // a ULONG, this will not work for entity bodies that // are larger than 4 GB. To work with large entity // bodies, we would have to use a ULONGLONG. TraceA("xmlrpc_server RPC2 handler processing " "RPC request."); // Process the RPC. xmlrpc_registry_process_call2( envP, global_registryP, XMLRPC_MEMBLOCK_CONTENTS(char, body), XMLRPC_MEMBLOCK_SIZE(char, body), NULL, &output); if (envP->fault_occurred) goto Done; // Initialize the HTTP response structure. INITIALIZE_HTTP_RESPONSE(&response, 200, "OK"); //Add the content-length StringCchPrintfA(szContentLength,MAX_ULONG_STR, "%lu", XMLRPC_MEMBLOCK_SIZE(char, output)); ADD_KNOWN_HEADER( response, HttpHeaderContentLength, szContentLength ); //Add the content-type ADD_KNOWN_HEADER(response, HttpHeaderContentType, "text/xml"); StringCchPrintfA(szServerHeader,20, "xmlrpc-c %s",XMLRPC_C_VERSION); ADD_KNOWN_HEADER(response, HttpHeaderServer, szServerHeader); //send the response result = HttpSendHttpResponse( hReqQueue, // ReqQueueHandle pRequest->RequestId, // Request ID HTTP_SEND_RESPONSE_FLAG_MORE_DATA, &response, // HTTP response NULL, // pReserved1 &bytesSent, // bytes sent (optional) NULL, // pReserved2 0, // Reserved3 NULL, // LPOVERLAPPED NULL // pReserved4 ); if(result != NO_ERROR) { TraceW(L"HttpSendHttpResponse failed with %lu", result); xmlrpc_env_set_fault_formatted( envP, XMLRPC_NETWORK_ERROR, "HttpSendHttpResponse failed with %lu", result); goto Done; } // Send entity body from a memory chunk. dataChunk.DataChunkType = HttpDataChunkFromMemory; dataChunk.FromMemory.BufferLength = (ULONG)XMLRPC_MEMBLOCK_SIZE(char, output); dataChunk.FromMemory.pBuffer = XMLRPC_MEMBLOCK_CONTENTS(char, output); result = HttpSendResponseEntityBody( hReqQueue, pRequest->RequestId, 0, // This is the last send. 1, // Entity Chunk Count. &dataChunk, NULL, NULL, 0, NULL, NULL ); if(result != NO_ERROR) { TraceW(L"HttpSendResponseEntityBody failed " L"with %lu", result); xmlrpc_env_set_fault_formatted( envP, XMLRPC_NETWORK_ERROR, "HttpSendResponseEntityBody failed with %lu", result); goto Done; } goto Done; break; default: TraceW(L"HttpReceiveRequestEntityBody failed with %lu", result); xmlrpc_env_set_fault_formatted( envP, XMLRPC_NETWORK_ERROR, "HttpReceiveRequestEntityBody failed " "with %lu", result); goto Done; } } while(TRUE); }
/* * This is a blocking function that merely sits on the request queue * for our URI and processes them one at a time. Once a request comes * in, we check it for content-type, content-length, and verb. As long * as the initial validations are done, we pass the request to the * processRPCCall() function, which collects the body of the request * and processes it. If we get an error back other than network type, * we are responsible for notifing the client. */ DWORD DoReceiveRequests( IN HANDLE hReqQueue, const xmlrpc_server_httpsys_parms * const parmsP ) { ULONG result; HTTP_REQUEST_ID requestId; DWORD bytesRead; PHTTP_REQUEST pRequest; PCHAR pRequestBuffer; ULONG RequestBufferLength; xmlrpc_env env; char szHeaderBuf[255]; long lContentLength; // Allocate a 2K buffer. Should be good for most requests, we'll grow // this if required. We also need space for a HTTP_REQUEST structure. RequestBufferLength = sizeof(HTTP_REQUEST) + 2048; pRequestBuffer = (PCHAR) ALLOC_MEM( RequestBufferLength ); if (pRequestBuffer == NULL) { return ERROR_NOT_ENOUGH_MEMORY; } pRequest = (PHTTP_REQUEST)pRequestBuffer; // Wait for a new request -- This is indicated by a NULL request ID. HTTP_SET_NULL_ID( &requestId ); for(;;) { RtlZeroMemory(pRequest, RequestBufferLength); result = HttpReceiveHttpRequest( hReqQueue, // Req Queue requestId, // Req ID 0, // Flags pRequest, // HTTP request buffer RequestBufferLength,// req buffer length &bytesRead, // bytes received NULL // LPOVERLAPPED ); if(NO_ERROR == result) { // Got a request with a filled buffer. switch(pRequest->Verb) { case HttpVerbPOST: TraceW(L"Got a POST request for %ws", pRequest->CookedUrl.pFullUrl); //Check if we need use authorization. if(parmsP->authfn) { xmlrpc_env_init(&env); if(pRequest->Headers.KnownHeaders[ HttpHeaderAuthorization].RawValueLength < 6) { xmlrpc_env_set_fault( &env, XMLRPC_REQUEST_REFUSED_ERROR, "Authorization header too short."); } else { //unencode the headers if(_strnicmp( "basic", pRequest->Headers.KnownHeaders[ HttpHeaderAuthorization].pRawValue,5) !=0) { #ifndef NDEBUG PCHAR pTmp = (PCHAR) ALLOC_MEM(pRequest->Headers.KnownHeaders[ HttpHeaderAuthorization ].RawValueLength + 1 ); if( pTmp ) { strncpy(pTmp, pRequest->Headers.KnownHeaders[ HttpHeaderAuthorization ].pRawValue, pRequest->Headers.KnownHeaders[ HttpHeaderAuthorization ].RawValueLength ); pTmp[pRequest->Headers.KnownHeaders[ HttpHeaderAuthorization ].RawValueLength] = 0; TraceA("Got HEADER [%s]",pTmp); FREE_MEM(pTmp); } #endif /* #ifndef NDEBUG */ xmlrpc_env_set_fault( &env, XMLRPC_REQUEST_REFUSED_ERROR, "Authorization header does not start " "with type 'basic'!"); } else { xmlrpc_mem_block * decoded; decoded = xmlrpc_base64_decode( &env, pRequest->Headers.KnownHeaders[ HttpHeaderAuthorization ].pRawValue+6, pRequest->Headers.KnownHeaders[ HttpHeaderAuthorization ].RawValueLength-6); if(!env.fault_occurred) { char *pDecodedStr; char *pUser; char *pPass; char *pColon; pDecodedStr = (char*) malloc(decoded->_size+1); memcpy(pDecodedStr, decoded->_block, decoded->_size); pDecodedStr[decoded->_size]='\0'; pUser = pPass = pDecodedStr; pColon=strchr(pDecodedStr,':'); if(pColon) { *pColon='\0'; pPass=pColon+1; //The authfn should set env to //fail if auth is denied. parmsP->authfn(&env,pUser,pPass); } else { xmlrpc_env_set_fault( &env, XMLRPC_REQUEST_REFUSED_ERROR, "Decoded auth not of the correct " "format."); } free(pDecodedStr); } if(decoded) XMLRPC_MEMBLOCK_FREE(char, decoded); } } if(env.fault_occurred) { //request basic authorization, as the user //did not provide it. xmlrpc_env_clean(&env); TraceW(L"POST request did not provide valid " L"authorization header."); result = SendHttpResponseAuthRequired( hReqQueue, pRequest); break; } xmlrpc_env_clean(&env); } //Check content type to make sure it is text/xml. memcpy(szHeaderBuf, pRequest->Headers.KnownHeaders[ HttpHeaderContentType ].pRawValue, pRequest->Headers.KnownHeaders[ HttpHeaderContentType ].RawValueLength); szHeaderBuf[pRequest->Headers.KnownHeaders[ HttpHeaderContentType ].RawValueLength] = '\0'; if (_stricmp(szHeaderBuf,"text/xml")!=0) { //We handle only text/xml data. Anything else //is not valid. TraceW(L"POST request had an unrecognized " L"content-type: %s", szHeaderBuf); result = SendHttpResponse( hReqQueue, pRequest, 400, "Bad Request", NULL ); break; } //Check content length to make sure it exists and //is not too big. memcpy(szHeaderBuf, pRequest->Headers.KnownHeaders[ HttpHeaderContentLength ].pRawValue, pRequest->Headers.KnownHeaders[ HttpHeaderContentLength ].RawValueLength); szHeaderBuf[pRequest->Headers.KnownHeaders[ HttpHeaderContentLength ].RawValueLength]='\0'; lContentLength = atol(szHeaderBuf); if (lContentLength<=0) { //Make sure a content length was supplied. TraceW(L"POST request did not include a " L"content-length", szHeaderBuf); result = SendHttpResponse( hReqQueue, pRequest, 411, "Length Required", NULL ); break; } if((size_t) lContentLength > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID)) { //Content-length is too big for us to handle TraceW(L"POST request content-length is too big " L"for us to handle: %d bytes", lContentLength); result = SendHttpResponse( hReqQueue, pRequest, 500, "content-length too large", NULL ); break; } //our initial validations of POST, content-type, //and content-length all check out. Collect and //pass the complete buffer to the XMLRPC-C library xmlrpc_env_init(&env); processRPCCall(&env,hReqQueue, pRequest); if (env.fault_occurred) { //if we fail and it is anything other than a //network error, we should return a failure //response to the client. if (env.fault_code != XMLRPC_NETWORK_ERROR) { if (env.fault_string) result = SendHttpResponse( hReqQueue, pRequest, 500, env.fault_string, NULL ); else result = SendHttpResponse( hReqQueue, pRequest, 500, "Unknown Error", NULL ); } } xmlrpc_env_clean(&env); break; default: //We handle only POST data. Anything else is not valid. TraceW(L"Got an unrecognized Verb request for URI %ws", pRequest->CookedUrl.pFullUrl); result = SendHttpResponse( hReqQueue, pRequest, 405, "Method Not Allowed", NULL ); break; } if(result != NO_ERROR) { break; } // Reset the Request ID so that we pick up the next request. HTTP_SET_NULL_ID( &requestId ); } else if(result == ERROR_MORE_DATA) { // The input buffer was too small to hold the request headers // We have to allocate more buffer & call the API again. // // When we call the API again, we want to pick up the request // that just failed. This is done by passing a RequestID. // This RequestID is picked from the old buffer. requestId = pRequest->RequestId; // Free the old buffer and allocate a new one. RequestBufferLength = bytesRead; FREE_MEM( pRequestBuffer ); pRequestBuffer = (PCHAR) ALLOC_MEM( RequestBufferLength ); if (pRequestBuffer == NULL) { result = ERROR_NOT_ENOUGH_MEMORY; break; } pRequest = (PHTTP_REQUEST)pRequestBuffer; } else if(ERROR_CONNECTION_INVALID == result && !HTTP_IS_NULL_ID(&requestId)) { // The TCP connection got torn down by the peer when we were // trying to pick up a request with more buffer. We'll just move // onto the next request. HTTP_SET_NULL_ID( &requestId ); } else { break; } } // for(;;) if(pRequestBuffer) { FREE_MEM( pRequestBuffer ); } return result; }
NDIS_STATUS HvlQueueExAccessRequest( _In_ PHVL pHvl, _In_ PVNIC pVNic, _In_ BOOLEAN fPnpOperation ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PHVL_EX_ACCESS_REQ pExReq = NULL, pPnpExReq = NULL; PHVL_PENDING_OP pPendingOp = NULL; ASSERT(HvlIsLocked(pHvl)); do { // All requests by the helper port are considered different if (!HvlIsHelperVNic(pHvl, pVNic)) { /* Does an exclusive access request for this VNIC already exist? */ pExReq = HvlGetNextReqForVNic(pHvl, pVNic, FALSE); } if (NULL != pExReq) { /* There is already an exclusive access request existing for this VNIC. */ /* If the request is not a PnP request simply ref-up */ if (!HvlIsPreAllocatedRequest(pHvl, pExReq)) { pExReq->ulRefCount++; MpTrace(COMP_HVL, DBG_NORMAL, ("VNIC (%d): Incremented refcount for an exclusive access requet. New ref = %d \n", VNIC_PORT_NO, pExReq->ulRefCount)); } else { /* a request already exists. However it is the PnP request. Make sure we do not use it for non-Pnp operation. If we did, we might get another PnP operation after this PnP operation is done but we won't be able to use the pre-allocated request. Instead try to allocate a new request now */ // pnp operations must be serialized ASSERT(!fPnpOperation); pPnpExReq = pExReq; pExReq = NULL; // allocate exclusive access request ndisStatus = ALLOC_MEM(pHvl->MiniportAdapterHandle, sizeof(HVL_EX_ACCESS_REQ), &pExReq); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("Failed to allocate memory for a new exclusive access request\n")); break; } // allocate pending operation ndisStatus = ALLOC_MEM(pHvl->MiniportAdapterHandle, sizeof(HVL_PENDING_OP), &pPendingOp); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("Failed to allocate memory for a new pending operation")); break; } pExReq->pVNic = pVNic; pExReq->ulRefCount = pPnpExReq->ulRefCount + 1; pPendingOp->Type = HVL_PENDING_OP_EX_ACCESS; pPendingOp->pvOpData= pExReq; // now insert this new request in the same place as the old request pPendingOp->Link.Flink = pHvl->PnpPendingOp.Link.Flink; pPendingOp->Link.Blink = pHvl->PnpPendingOp.Link.Blink; pHvl->PnpPendingOp.Link.Flink->Blink = &pPendingOp->Link; pHvl->PnpPendingOp.Link.Blink->Flink = &pPendingOp->Link; // re-init the pre-allocated request since we are no longer using it HvlInitPreAllocatedOp(pHvl); } } else { /* This is the only exclusive access request for the HVL. Create a new request */ if (fPnpOperation) { ASSERT(pHvl->PnpPendingOp.Link.Blink == NULL && pHvl->PnpPendingOp.Link.Flink == NULL); pExReq = pHvl->pPnpOpExReq; } else { ndisStatus = ALLOC_MEM(pHvl->MiniportAdapterHandle, sizeof(HVL_EX_ACCESS_REQ), &pExReq); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("Failed to allocate memory for a new exclusive access request\n")); break; } } pExReq->pVNic = pVNic; pExReq->ulRefCount = 1; ndisStatus = HvlQueuePendingOperation(pHvl, HVL_PENDING_OP_EX_ACCESS, pExReq, fPnpOperation); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("HvlQueuePendingOperation failed 0x%x\n", ndisStatus)); break; } MpTrace(COMP_HVL, DBG_NORMAL, ("Queued an exclusive access requet for VNIC (%d)\n", VNIC_PORT_NO)); } } while (FALSE); if (NDIS_FAILURE(ndisStatus)) { if (pExReq && !fPnpOperation) { HvlDeleteExAccessRequest(pHvl, pExReq); } if (pPendingOp) { FREE_MEM(pPendingOp); } } return ndisStatus; }
NDIS_STATUS VNic11JoinBSS( _In_ PVNIC pVNic, _In_ PMP_BSS_DESCRIPTION BSSDescription, _In_ ULONG JoinFailureTimeout, _In_ PORT11_GENERIC_CALLBACK_FUNC CompletionHandler ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; BOOLEAN fLocked = FALSE; BOOLEAN fProcessReqNow = FALSE; PVNIC_COMPLETION_CTX pCtx = NULL; do { VNicLock(pVNic); fLocked = TRUE; ndisStatus = VNicCanProcessReqNow(pVNic, &fProcessReqNow); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): VNicCanProcessReqNow failed 0x%x\n", VNIC_PORT_NO, ndisStatus)); break; } if (fProcessReqNow) { ndisStatus = ALLOC_MEM(pVNic->MiniportAdapterHandle, sizeof(VNIC_COMPLETION_CTX), &pCtx); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("VNic(%d): Failed to allocate memory for a new completion context \n", VNIC_PORT_NO)); /* Do not call the station's callback function since the station doesn't expect to be called back if there is a failure */ break; } pCtx->CompletionFn = CompletionHandler; ndisStatus = VNicJoinBSSHelper(pVNic, BSSDescription, JoinFailureTimeout, pCtx); if (NDIS_STATUS_PENDING != ndisStatus) { MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): VNicJoinBSSHelper completed synchronously %!x!\n", VNIC_PORT_NO, ndisStatus)); /* The call to the hardware completed synchronously. Do not call the station's callback function. */ FREE_MEM(pCtx); break; } } else { /* We are not currently active or there are pending operations. Queue the Join request internally */ ndisStatus = VNicQueueJoinRequest( pVNic, BSSDescription, JoinFailureTimeout, CompletionHandler ); if (NDIS_STATUS_SUCCESS == ndisStatus) { MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): Queued the join request \n", VNIC_PORT_NO)); // Return pending since the request is not going to be completed synchrnously ndisStatus = NDIS_STATUS_PENDING; } else { MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): VNicQueueJoinRequest failed %!x!\n", VNIC_PORT_NO, ndisStatus)); } } } while (FALSE); if (fLocked) { VNicUnlock(pVNic); } return ndisStatus; }
NDIS_STATUS VNicQueueStartBSSRequest( _In_ PVNIC pVNic, _In_ PMP_BSS_DESCRIPTION BSSDescription, _In_ PORT11_GENERIC_CALLBACK_FUNC CompletionHandler ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PSTART_BSS_REQ pStartBssReq = NULL; PMP_BSS_DESCRIPTION pBSSDescCopy = NULL; ULONG ulBufferSize = 0; ASSERT(VNicIsLocked(pVNic)); do { ndisStatus = ALLOC_MEM(pVNic->MiniportAdapterHandle, sizeof(START_BSS_REQ), &pStartBssReq); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("VNic(%d): Failed to allocate memory for a new start BSS request\n", VNIC_PORT_NO)); break; } ulBufferSize = FIELD_OFFSET(MP_BSS_DESCRIPTION, IEBlobs) + BSSDescription->IEBlobsSize; ndisStatus = ALLOC_MEM(pVNic->MiniportAdapterHandle, ulBufferSize, &pBSSDescCopy); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("VNic(%d): Failed to allocate memory for a new BSS description\n", VNIC_PORT_NO)); break; } NdisMoveMemory(pBSSDescCopy, BSSDescription, ulBufferSize); pStartBssReq->BSSDescription = pBSSDescCopy; pStartBssReq->CompletionHandler = CompletionHandler; ndisStatus = VNicQueuePendingOperation(pVNic, PENDING_OP_START_BSS_REQ, pStartBssReq, FALSE); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("VNic(%d): VNicQueuePendingOperation failed 0x%x\n", VNIC_PORT_NO, ndisStatus)); break; } MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): Queued a start BSS request\n", VNIC_PORT_NO)); } while (FALSE); if (NDIS_STATUS_SUCCESS != ndisStatus) { if (pBSSDescCopy) { FREE_MEM(pBSSDescCopy); } if (pStartBssReq) { FREE_MEM(pStartBssReq); } } return ndisStatus; }
/*===========================================================================* * vm_allocpage * *===========================================================================*/ PUBLIC void *vm_allocpage(phys_bytes *phys, int reason) { /* Allocate a page for use by VM itself. */ phys_bytes newpage; vir_bytes loc; pt_t *pt; int r; static int level = 0; void *ret; pt = &vmp->vm_pt; vm_assert(reason >= 0 && reason < VMP_CATEGORIES); level++; vm_assert(level >= 1); vm_assert(level <= 2); if(level > 1 || !(vmp->vm_flags & VMF_HASPT) || !meminit_done) { int r; void *s; s=vm_getsparepage(phys); level--; if(!s) { util_stacktrace(); printf("VM: warning: out of spare pages\n"); } return s; } /* VM does have a pagetable, so get a page and map it in there. * Where in our virtual address space can we put it? */ loc = findhole(pt, arch_vir2map(vmp, vmp->vm_stacktop), vmp->vm_arch.vm_data_top); if(loc == NO_MEM) { level--; printf("VM: vm_allocpage: findhole failed\n"); return NULL; } /* Allocate page of memory for use by VM. As VM * is trusted, we don't have to pre-clear it. */ if((newpage = ALLOC_MEM(CLICKSPERPAGE, 0)) == NO_MEM) { level--; printf("VM: vm_allocpage: ALLOC_MEM failed\n"); return NULL; } *phys = CLICK2ABS(newpage); /* Map this page into our address space. */ if((r=pt_writemap(pt, loc, *phys, I386_PAGE_SIZE, I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE, 0)) != OK) { FREE_MEM(newpage, CLICKSPERPAGE); printf("vm_allocpage writemap failed\n"); level--; return NULL; } if((r=sys_vmctl(SELF, VMCTL_FLUSHTLB, 0)) != OK) { vm_panic("VMCTL_FLUSHTLB failed", r); } level--; /* Return user-space-ready pointer to it. */ ret = (void *) arch_map2vir(vmp, loc); return ret; }
NDIS_STATUS Hvl11Allocate( _In_ NDIS_HANDLE MiniportAdapterHandle, _Outptr_result_maybenull_ PHVL* ppHvl, _In_ PADAPTER pAdapter ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PHVL pHvl = NULL; NDIS_HANDLE ctxSWorkItemHandle = NULL, notificationsWorkItemHandle = NULL; BOOLEAN fFreeCtxSWorkItemHandle = FALSE, fFreeNotifWorkItemHandle = FALSE; PHVL_EX_ACCESS_REQ pExReq = NULL; ASSERT(MiniportAdapterHandle && ppHvl && pAdapter); *ppHvl = NULL; do { ndisStatus = ALLOC_MEM(MiniportAdapterHandle, sizeof(HVL), &pHvl); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("Failed to allocate memory for a new HVL")); break; } // the list heads should be the first ones to be initialized. This allows us to free things // correctly if Free is called without Initialize being called in between InitializeListHead(&pHvl->VNiclist); InitializeListHead(&pHvl->InactiveContextList); InitializeListHead(&pHvl->PendingOpQueue); InitializeListHead(&pHvl->NotificationsQueue); // Allocate memory for fields inside the HVL structure // pre-allocate the exclusive access request structure for PnP related exclusive accesses ndisStatus = ALLOC_MEM(MiniportAdapterHandle, sizeof(HVL_EX_ACCESS_REQ), &pExReq); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("Failed to allocate memory for exclusive access request")); break; } NdisAllocateSpinLock(&(pHvl->Lock)); // Allocate the context switch work item ctxSWorkItemHandle = NdisAllocateIoWorkItem(MiniportAdapterHandle); if(NULL == ctxSWorkItemHandle) { MpTrace (COMP_HVL, DBG_SERIOUS, ("NdisAllocateIoWorkItem failed")); ndisStatus = NDIS_STATUS_RESOURCES; break; } fFreeCtxSWorkItemHandle = TRUE; notificationsWorkItemHandle = NdisAllocateIoWorkItem(MiniportAdapterHandle); if(NULL == notificationsWorkItemHandle) { MpTrace (COMP_HVL, DBG_SERIOUS, ("NdisAllocateIoWorkItem failed")); ndisStatus = NDIS_STATUS_RESOURCES; break; } fFreeNotifWorkItemHandle = TRUE; pHvl->MiniportAdapterHandle = MiniportAdapterHandle; pHvl->Adapter = pAdapter; pHvl->CtxSWorkItemHandle = ctxSWorkItemHandle; pHvl->NotificationsWorkItemHandle = notificationsWorkItemHandle; pHvl->fVirtualizationEnabled = TRUE; pHvl->pPnpOpExReq = pExReq; *ppHvl = pHvl; }while (FALSE); if (NDIS_STATUS_SUCCESS != ndisStatus) { if (fFreeNotifWorkItemHandle) { NdisFreeIoWorkItem(notificationsWorkItemHandle); } if (fFreeCtxSWorkItemHandle) { NdisFreeIoWorkItem(ctxSWorkItemHandle); } if (pExReq) { FREE_MEM(pExReq); } if (pHvl) { FREE_MEM(pHvl); } } return ndisStatus; }
DWORD WINAPI WahCreateContextTable( LPCONTEXT_TABLE * Table, DWORD Flags ) /*++ Routine Description: Creates a new context table. Arguments: Table - If successful, receives a pointer to the newly created context table. Flags - Flags to control the tables behaviour. Return Value: DWORD - NO_ERROR if successful, a Win32 error code if not. --*/ { DWORD newTableSize; LPCONTEXT_TABLE newTable; // // Create the new context table. // newTableSize = sizeof(*newTable); if( Flags & WAH_CONTEXT_FLAG_SERIALIZE ) { newTableSize += sizeof(CRITICAL_SECTION); } newTable = ALLOC_MEM( newTableSize ); if( newTable != NULL ) { // // Initialize it. // if( Flags & WAH_CONTEXT_FLAG_SERIALIZE ) { InitializeCriticalSection( TABLE_TO_LOCK( newTable ) ); } newTable->Flags = Flags; newTable->LookupArraySize = INITIAL_ARRAY_ENTRIES; newTable->LookupArray = ALLOC_MEM( INITIAL_ARRAY_ENTRIES * sizeof(LPVOID) ); if( newTable->LookupArray != NULL ) { // // Success! // *Table = newTable; return NO_ERROR; } // // Allocated the CONTEXT_TABLE, but could not allocate the // lookup array. Bummer. // FREE_MEM( newTable ); newTable = NULL; } *Table = newTable; return ERROR_NOT_ENOUGH_MEMORY; } // WahCreateContextTable
AR_NAMESPACE_BEGIN //#define USE_C_MALLOC 1 #if defined(USE_C_MALLOC) #define ALLOC_MEM(_heap, _bytes) malloc((_bytes)) #define FREE_MEM(_heap, _ptr) free((_ptr)) #define REALLOC_MEM(_heap, _ptr, _size) realloc((_ptr), (_size)) #else #define ALLOC_MEM(_heap, _bytes) AR_AllocFromHeap((_heap), (_bytes)) #define FREE_MEM(_heap, _ptr) AR_FreeToHeap((_heap), (_ptr)) #define REALLOC_MEM(_heap, _ptr, _size) AR_ReallocFromHeap((_heap), (_ptr), (_size)) #endif void alloc_test() { arHeap_t *heap = NULL; #if !defined(USE_C_MALLOC) heap = AR_CreateHeap(); #endif std::vector<size_t> mem_size_set; std::vector<void*> mem_ptr_set; //srand(time(NULL)); for(size_t i = 0; i < 10000; ++i) { size_t n = 0; /* while(n == 0) { n = AR_rand64() % 102767; if(n < 102767)n = 102767 + AR_rand64() % 32768; } mem_size_set.push_back(n); */ while(n == 0) { n = AR_rand64() % 32768; } mem_size_set.push_back(n); while(n == 0) { n = AR_rand64() % 256; } mem_size_set.push_back(n); } size_t size_cnt = mem_size_set.size(); for(size_t i = 0; i < size_cnt; ++i) { size_t n = mem_size_set[i]; void *p = ALLOC_MEM(heap, n); memset(p, 'a', n); AR_ASSERT(p != NULL); mem_ptr_set.push_back(p); if(AR_rand32() % 8 > 0) { size_t idx = AR_rand32() % mem_ptr_set.size(); void *ptr = mem_ptr_set[idx]; mem_ptr_set.erase(mem_ptr_set.begin() + idx); FREE_MEM(heap, ptr); } } size_t ptr_cnt = mem_ptr_set.size(); for(size_t i = 0; i < ptr_cnt; ++i) { void *ptr = mem_ptr_set[i]; AR_ASSERT(ptr != NULL); FREE_MEM(heap, ptr); mem_ptr_set[i] = NULL; } if(heap) { AR_DestroyHeap(heap); } }