HTTPAPIEX_SAS_HANDLE HTTPAPIEX_SAS_Create(STRING_HANDLE key, STRING_HANDLE uriResource, STRING_HANDLE keyName)
{
    HTTPAPIEX_SAS_HANDLE result = NULL;
    if (key == NULL)
    {
        /*Codes_SRS_HTTPAPIEXSAS_06_001: [If the parameter key is NULL then HTTPAPIEX_SAS_Create shall return NULL.]*/
        LogError("No key passed to HTTPAPIEX_SAS_Create.\r\n");
    }
    else if (uriResource == NULL)
    {
        /*Codes_SRS_HTTPAPIEXSAS_06_002: [If the parameter uriResource is NULL then HTTPAPIEX_SAS_Create shall return NULL.]*/
        LogError("No uri resource passed to HTTPAPIEX_SAS_Create.\r\n");
    }
    else if (keyName == NULL)
    {
        /*Codes_SRS_HTTPAPIEXSAS_06_003: [If the parameter keyName is NULL then HTTPAPIEX_SAS_Create shall return NULL.]*/
        LogError("No key name passed to HTTPAPIEX_SAS_Create.\r\n");
    }
    else
    {
        HTTPAPIEX_SAS_STATE* state = malloc(sizeof(HTTPAPIEX_SAS_STATE));
        /*Codes_SRS_HTTPAPIEXSAS_06_004: [If there are any other errors in the instantiation of this handle then HTTPAPIEX_SAS_Create shall return NULL.]*/
        if (state != NULL)
        {
            state->key = NULL;
            state->uriResource = NULL;
            state->keyName = NULL;
            if (((state->key = STRING_clone(key)) == NULL) ||
                ((state->uriResource = STRING_clone(uriResource)) == NULL) ||
                ((state->keyName = STRING_clone(keyName)) == NULL))
            {
                /*Codes_SRS_HTTPAPIEXSAS_06_004: [If there are any other errors in the instantiation of this handle then HTTPAPIEX_SAS_Create shall return NULL.]*/
                LogError("Unable to clone the arguments.\r\n");
                HTTPAPIEX_SAS_Destroy(state);
            }
            else
            {
                result = state;
            }
        }
    }
    return result;
}
static IOTHUB_DEVICE_METHOD_RESULT sendHttpRequestDeviceMethod(IOTHUB_SERVICE_CLIENT_DEVICE_METHOD_HANDLE serviceClientDeviceMethodHandle, IOTHUB_DEVICEMETHOD_REQUEST_MODE iotHubDeviceMethodRequestMode, const char* deviceName, BUFFER_HANDLE deviceJsonBuffer, BUFFER_HANDLE responseBuffer)
{
    IOTHUB_DEVICE_METHOD_RESULT result;

    STRING_HANDLE uriResouce;
    STRING_HANDLE accessKey;
    STRING_HANDLE keyName;
    HTTPAPIEX_SAS_HANDLE httpExApiSasHandle;
    HTTPAPIEX_HANDLE httpExApiHandle;
    HTTP_HEADERS_HANDLE httpHeader;

    if ((uriResouce = STRING_construct(serviceClientDeviceMethodHandle->hostname)) == NULL)
    {
        LogError("STRING_construct failed for uriResource");
        result = IOTHUB_DEVICE_METHOD_ERROR;
    }
    else if ((accessKey = STRING_construct(serviceClientDeviceMethodHandle->sharedAccessKey)) == NULL)
    {
        LogError("STRING_construct failed for accessKey");
        STRING_delete(uriResouce);
        result = IOTHUB_DEVICE_METHOD_ERROR;
    }
    else if ((keyName = STRING_construct(serviceClientDeviceMethodHandle->keyName)) == NULL)
    {
        LogError("STRING_construct failed for keyName");
        STRING_delete(accessKey);
        STRING_delete(uriResouce);
        result = IOTHUB_DEVICE_METHOD_ERROR;
    }
    else if ((httpHeader = createHttpHeader()) == NULL)
    {
        LogError("HttpHeader creation failed");
        STRING_delete(keyName);
        STRING_delete(accessKey);
        STRING_delete(uriResouce);
        result = IOTHUB_DEVICE_METHOD_ERROR;
    }
    else if ((httpExApiSasHandle = HTTPAPIEX_SAS_Create(accessKey, uriResouce, keyName)) == NULL)
    {
        LogError("HTTPAPIEX_SAS_Create failed");
        HTTPHeaders_Free(httpHeader);
        STRING_delete(keyName);
        STRING_delete(accessKey);
        STRING_delete(uriResouce);
        result = IOTHUB_DEVICE_METHOD_HTTPAPI_ERROR;
    }
    else if ((httpExApiHandle = HTTPAPIEX_Create(serviceClientDeviceMethodHandle->hostname)) == NULL)
    {
        LogError("HTTPAPIEX_Create failed");
        HTTPAPIEX_SAS_Destroy(httpExApiSasHandle);
        HTTPHeaders_Free(httpHeader);
        STRING_delete(keyName);
        STRING_delete(accessKey);
        STRING_delete(uriResouce);
        result = IOTHUB_DEVICE_METHOD_HTTPAPI_ERROR;
    }
    else 
    {
        HTTPAPI_REQUEST_TYPE httpApiRequestType = HTTPAPI_REQUEST_GET;
        STRING_HANDLE relativePath;
        unsigned int statusCode = 0;
        unsigned char is_error = 0;

        if (iotHubDeviceMethodRequestMode == IOTHUB_DEVICEMETHOD_REQUEST_INVOKE)
        {
            httpApiRequestType = HTTPAPI_REQUEST_POST;
        }
        else
        {
            is_error = 1;
        }

        if (is_error)
        {
            LogError("Invalid request type");
            result = IOTHUB_DEVICE_METHOD_HTTPAPI_ERROR;
        }
        else
        {
            if ((relativePath = createRelativePath(iotHubDeviceMethodRequestMode, deviceName)) == NULL)
            {
                LogError("Failure creating relative path");
                result = IOTHUB_DEVICE_METHOD_ERROR;
            }
            else if (HTTPAPIEX_SAS_ExecuteRequest(httpExApiSasHandle, httpExApiHandle, httpApiRequestType, STRING_c_str(relativePath), httpHeader, deviceJsonBuffer, &statusCode, NULL, responseBuffer) != HTTPAPIEX_OK)
            {
                LogError("HTTPAPIEX_SAS_ExecuteRequest failed");
                STRING_delete(relativePath);
                result = IOTHUB_DEVICE_METHOD_HTTPAPI_ERROR;
            }
            else
            {
                STRING_delete(relativePath);
                if (statusCode == 200)
                {
                    result = IOTHUB_DEVICE_METHOD_OK;
                }
                else
                {
                    LogError("Http Failure status code %d.", statusCode);
                    result = IOTHUB_DEVICE_METHOD_ERROR;
                }
            }
        }
        HTTPAPIEX_Destroy(httpExApiHandle);
        HTTPAPIEX_SAS_Destroy(httpExApiSasHandle);
        HTTPHeaders_Free(httpHeader);
        STRING_delete(keyName);
        STRING_delete(accessKey);
        STRING_delete(uriResouce);
    }
    return result;
}
static BUFFER_HANDLE sendDeviceRegistryInfo(IOTHUB_ACCOUNT_INFO* accountInfo, BUFFER_HANDLE deviceBuffer, HTTPAPI_REQUEST_TYPE requestType)
{
    BUFFER_HANDLE result;

    STRING_HANDLE accessKey = STRING_construct(accountInfo->sharedAccessKey);
    STRING_HANDLE uriResouce = STRING_construct(accountInfo->hostname);
    STRING_HANDLE keyName = STRING_construct(accountInfo->keyName);
    if (accessKey != NULL && uriResouce != NULL && keyName != NULL)
    {
        HTTPAPIEX_SAS_HANDLE httpHandle = HTTPAPIEX_SAS_Create(accessKey, uriResouce, keyName);
        if (httpHandle != NULL)
        {
            HTTPAPIEX_HANDLE httpExApi = HTTPAPIEX_Create(accountInfo->hostname);
            if (httpExApi == NULL)
            {
                LogError("Failure creating httpApiEx with hostname: %s.\r\n", accountInfo->hostname);
                result = NULL;
            }
            else
            {
                char relativePath[256];
                if (sprintf_s(relativePath, 256, RELATIVE_PATH_FMT, accountInfo->deviceId, URL_API_VERSION) <= 0)
                {
                    LogError("Failure creating relative path.\r\n");
                    result = NULL;
                }
                else
                {

                    unsigned int statusCode = 0;

                    // Send PUT method to url
                    HTTP_HEADERS_HANDLE httpHeader = getContentHeaders((deviceBuffer == NULL) ? true : false);
                    if (httpHeader == NULL)
                    {
                        result = NULL;
                    }
                    else
                    {
                        BUFFER_HANDLE responseContent = BUFFER_new();
                        if (HTTPAPIEX_SAS_ExecuteRequest(httpHandle, httpExApi, requestType, relativePath, httpHeader, deviceBuffer, &statusCode, NULL, responseContent) != HTTPAPIEX_OK)
                        {
                            LogError("Failure calling HTTPAPIEX_SAS_ExecuteRequest.\r\n");
                            result = NULL;
                        }
                        else
                        {
                            // 409 means the device is already created so we don't need
                            // to create another one.
                            if (statusCode != 409 && statusCode > 300)
                            {
                                LogError("Http Failure status code %d.\r\n", statusCode);
                                BUFFER_delete(responseContent);
                                result = NULL;
                            }
                            else
                            {
                                result = responseContent;
                            }
                        }
                    }
                    HTTPHeaders_Free(httpHeader);
                }
                HTTPAPIEX_Destroy(httpExApi);
            }
            HTTPAPIEX_SAS_Destroy(httpHandle);
        }
        else
        {
            LogError("Http Failure with HTTPAPIEX_SAS_Create.\r\n");
            result = NULL;
        }
    }
    STRING_delete(accessKey);
    STRING_delete(uriResouce);
    STRING_delete(keyName);
    return result;
}