Exemple #1
0
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;
}
Exemple #2
0
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;
    
}
Exemple #3
0
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;
    
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #6
0
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;
}
Exemple #7
0
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;
}
Exemple #8
0
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;
}
Exemple #9
0
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;
}
Exemple #12
0
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;
}
Exemple #13
0
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;
}
Exemple #14
0
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;
}
Exemple #16
0
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;
}
Exemple #17
0
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);
		}
}