454 lines
15 KiB
C++
454 lines
15 KiB
C++
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
// PARTICULAR PURPOSE.
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
const char APP_DESCRIPTION[] = "Location API SDK Default Location Sample";
|
|
// The goal of this application is to show you how to set
|
|
// the default location using the Location API.
|
|
|
|
// This application prompts the user to specify location data that
|
|
// is used to create a civic address location report and a
|
|
// latitude/longitude report, and prints the report fields.
|
|
// It then sets the default location, which can then be viewed in
|
|
// Control Panel.
|
|
|
|
// This sample must be run as administrator for the call to
|
|
// IDefaultLocation::SetReport to succeed.
|
|
|
|
|
|
#include <windows.h>
|
|
#include <atlbase.h>
|
|
#include <atlcom.h>
|
|
#include <LocationApi.h>
|
|
#include <assert.h>
|
|
#include <conio.h> // For _getch()
|
|
|
|
#include "LocationReportObject.h"
|
|
|
|
// Function for prompting the user to enter a new location.
|
|
HRESULT EnterLocation(CLocationReport * pLocationReport);
|
|
// Function to print the values in a civic address report.
|
|
void PrintCivicAddress(ICivicAddressReport * pDefaultCivicAddressReport);
|
|
// Function to print the values in a latitude/longitude report.
|
|
void PrintLatLong(ILatLongReport *pLatLongReport);
|
|
// Function to print the GUID associated with a location report.
|
|
void PrintGUID(REFGUID guid);
|
|
// Function to print the system time associated with a location report.
|
|
void PrintTime(const SYSTEMTIME systime);
|
|
// Function to read a line from standard input and remove the newline character.
|
|
WCHAR * SafeGetws(wchar_t* dest, int size);
|
|
|
|
const wchar_t PROMPT_ADDRESS1[] =
|
|
L"\nEnter the first line of the street address to set. \nInput that is not less than 80 characters will be truncated\n";
|
|
const wchar_t PROMPT_ADDRESS2[] =
|
|
L"\nEnter the second line of the street address to set.\n";
|
|
const wchar_t PROMPT_CITY[] =
|
|
L"\nEnter the city to set.\n";
|
|
const wchar_t PROMPT_STATEPROVINCE[] =
|
|
L"\nEnter the state/province to set.\n";
|
|
const wchar_t PROMPT_POSTALCODE[] =
|
|
L"\nEnter the postal code to set.\n";
|
|
const wchar_t PROMPT_COUNTRYREGION[] =
|
|
L"\nEnter a valid ISO-3166 two-letter country code.\n";
|
|
const wchar_t PROMPT_LATITUDE[] =
|
|
L"\nEnter a valid latitude between -90 and 90.\n";
|
|
const wchar_t PROMPT_LONGITUDE[] =
|
|
L"\nEnter a valid longitude between -180 and 180.\n";
|
|
const wchar_t PROMPT_ERRORRADIUS[] =
|
|
L"\nEnter a non-zero error radius for the latitude/longitude location, in meters.\n";
|
|
const wchar_t PROMPT_ALTITUDE[] =
|
|
L"\nEnter a value for altitude.\n";
|
|
const wchar_t PROMPT_ALTITUDEERROR[] =
|
|
L"\nEnter a value for the altitude margin of error, in meters.\n";
|
|
const int ADDRESS_FIELD_LENGTH = 80;
|
|
const int COUNTRYREGION_FIELD_LENGTH = 4; // 2-digit or 3-digit code + newline
|
|
class CInitializeATL : public CAtlExeModuleT<CInitializeATL>{};
|
|
// Initializes ATL for this application. This also does CoInitialize for us
|
|
CInitializeATL g_InitializeATL;
|
|
|
|
int wmain()
|
|
{
|
|
printf("%s.\n", APP_DESCRIPTION);
|
|
|
|
// The location report object
|
|
CComObject<CLocationReport> *pNewLocationReport = NULL;
|
|
// Interface for civic address reports
|
|
CComPtr<ICivicAddressReport> spCivicAddressReport;
|
|
// Interface for latitude/longitude reports
|
|
CComPtr<ILatLongReport> spLatLongReport;
|
|
// Interface for setting default location
|
|
CComPtr<IDefaultLocation> spDefaultLocation;
|
|
|
|
// Create the new location report.
|
|
HRESULT hr = CComObject<CLocationReport>::CreateInstance(&pNewLocationReport);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pNewLocationReport->AddRef();
|
|
hr = EnterLocation(pNewLocationReport);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// CoCreate the default location object for getting and setting default location
|
|
hr = spDefaultLocation.CoCreateInstance(CLSID_DefaultLocation);
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pNewLocationReport->QueryInterface(IID_PPV_ARGS(&spCivicAddressReport));
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// set the civic address fields of the Default Location
|
|
hr = spDefaultLocation->SetReport(IID_ICivicAddressReport, spCivicAddressReport);
|
|
if (E_INVALIDARG == hr)
|
|
{
|
|
wprintf(L"The civic address report has invalid data. ");
|
|
wprintf(L"Country/region must be a valid ISO-3166 2-letter or 3-letter code.\n");
|
|
}
|
|
else if (E_ACCESSDENIED == hr)
|
|
{
|
|
wprintf(L"Administrator privilege required.\n");
|
|
}
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pNewLocationReport->QueryInterface(IID_PPV_ARGS(&spLatLongReport));
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = spDefaultLocation->SetReport(IID_ILatLongReport, spLatLongReport);
|
|
if (E_INVALIDARG == hr)
|
|
{
|
|
wprintf(L"The latitude/longitude report has invalid data. ");
|
|
wprintf(L"Latitude must be between -90 and 90.\n Longitude must be between -180 and 180.\n");
|
|
}
|
|
else if (E_ACCESSDENIED == hr)
|
|
{
|
|
wprintf(L"Administrator privilege required.\n");
|
|
}
|
|
}
|
|
|
|
pNewLocationReport->Release();
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
// Gets new location data from the user, and prints the report data.
|
|
// The location data includes fields for both a civic address report
|
|
// and a latitude/longitude report.
|
|
// The error radius, altitude, and altitude error fields are not
|
|
// displayed in the Default Location Control Panel, but they are
|
|
// available from the Location API.
|
|
HRESULT EnterLocation(CLocationReport * pLocationReport)
|
|
{
|
|
WCHAR address1[ADDRESS_FIELD_LENGTH];
|
|
WCHAR address2[ADDRESS_FIELD_LENGTH];
|
|
WCHAR city[ADDRESS_FIELD_LENGTH];
|
|
WCHAR stateprovince[ADDRESS_FIELD_LENGTH];
|
|
WCHAR zipcode[ADDRESS_FIELD_LENGTH];
|
|
WCHAR countryregion[COUNTRYREGION_FIELD_LENGTH]; // ISO-3166 2-digit or 3-digit code
|
|
DOUBLE latitude = 0;
|
|
DOUBLE longitude = 0;
|
|
DOUBLE errorradius = 0;
|
|
DOUBLE altitude = 0;
|
|
DOUBLE altitudeerror = 0;
|
|
int numberfieldsread = 0; // number of fields successfully read by wscanf_s
|
|
|
|
// Interface for civic address report
|
|
CComPtr<ICivicAddressReport> spCivicAddressReport;
|
|
// Interface for latitude/longitude report
|
|
CComPtr<ILatLongReport> spLatLongReport;
|
|
|
|
// prompt user to enter line 1 of the street address.
|
|
wprintf(PROMPT_ADDRESS1);
|
|
SafeGetws(address1, ARRAYSIZE(address1));
|
|
fflush(stdin);
|
|
// Set line 1 of the street address in the new report
|
|
CComBSTR bstrAddress1(address1);
|
|
HRESULT hr = pLocationReport->SetAddressLine1(bstrAddress1);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// prompt user to enter line 2 of the street address.
|
|
wprintf(PROMPT_ADDRESS2);
|
|
SafeGetws(address2, ARRAYSIZE(address2));
|
|
fflush(stdin);
|
|
// Set line 2 of the street address in the new report
|
|
CComBSTR bstrAddress2(address2);
|
|
hr = pLocationReport->SetAddressLine2(bstrAddress2);
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// prompt user to enter the city.
|
|
wprintf(PROMPT_CITY);
|
|
SafeGetws(city, ARRAYSIZE(city));
|
|
fflush(stdin);
|
|
// Set the city in the new report
|
|
CComBSTR bstrCity(city);
|
|
hr = pLocationReport->SetCity(bstrCity);
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// prompt user to enter the state/province.
|
|
wprintf(PROMPT_STATEPROVINCE);
|
|
SafeGetws(stateprovince, ARRAYSIZE(city));
|
|
fflush(stdin);
|
|
// Set the state/province in the new report
|
|
CComBSTR bstrStateProvince(stateprovince);
|
|
hr = pLocationReport->SetStateProvince(bstrStateProvince);
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// prompt user to enter the postal code.
|
|
wprintf(PROMPT_POSTALCODE);
|
|
SafeGetws(zipcode, ARRAYSIZE(zipcode));
|
|
fflush(stdin);
|
|
// Set the postal code in the new report
|
|
CComBSTR bstrZipCode(zipcode);
|
|
hr = pLocationReport->SetPostalCode(bstrZipCode);
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// prompt user to enter the country code.
|
|
wprintf(PROMPT_COUNTRYREGION);
|
|
SafeGetws(countryregion, ARRAYSIZE(countryregion));
|
|
fflush(stdin);
|
|
// Set the country/region in the new report
|
|
CComBSTR bstrCountryRegion(countryregion);
|
|
hr = pLocationReport->SetCountryRegion(bstrCountryRegion);
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// prompt the user to enter latitude
|
|
wprintf(PROMPT_LATITUDE);
|
|
numberfieldsread = wscanf_s(L"%lf", &latitude);
|
|
fflush(stdin);
|
|
if (0 == numberfieldsread)
|
|
{
|
|
wprintf(L"Error reading input. The report field will be set to zero.\n");
|
|
}
|
|
else
|
|
{
|
|
// Set the latitude
|
|
hr = pLocationReport->SetLatitude(latitude);
|
|
}
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// prompt the user to enter longitude
|
|
wprintf(PROMPT_LONGITUDE);
|
|
numberfieldsread = wscanf_s(L"%lf", &longitude);
|
|
fflush(stdin);
|
|
if (0 == numberfieldsread)
|
|
{
|
|
wprintf(L"Error reading input. The report field will be set to zero.\n");
|
|
}
|
|
else
|
|
{
|
|
// Set the longitude
|
|
hr = pLocationReport->SetLongitude(longitude);
|
|
}
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// prompt the user to enter the error radius for the latitude/longitude
|
|
wprintf(PROMPT_ERRORRADIUS);
|
|
numberfieldsread = wscanf_s(L"%lf", &errorradius);
|
|
fflush(stdin);
|
|
if (0 == numberfieldsread)
|
|
{
|
|
wprintf(L"Error reading input. The report field will be set to a default value.\n");
|
|
}
|
|
else
|
|
{
|
|
// Set the error radius
|
|
hr = pLocationReport->SetErrorRadius(errorradius);
|
|
}
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// prompt the user to enter altitude
|
|
wprintf(PROMPT_ALTITUDE);
|
|
numberfieldsread = wscanf_s(L"%lf", &altitude);
|
|
fflush(stdin);
|
|
if (0 == numberfieldsread)
|
|
{
|
|
wprintf(L"Error reading input. The report field will be set to zero.\n");
|
|
}
|
|
else
|
|
{
|
|
// Set the altitude
|
|
hr = pLocationReport->SetAltitude(altitude);
|
|
}
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// prompt the user to enter altitude error
|
|
wprintf(PROMPT_ALTITUDEERROR);
|
|
numberfieldsread = wscanf_s(L"%lf", &altitudeerror);
|
|
fflush(stdin);
|
|
if (0 == numberfieldsread)
|
|
{
|
|
wprintf(L"Error reading input. The report field will be set to zero.\n");
|
|
}
|
|
else
|
|
{
|
|
// Set the altitude error
|
|
hr = pLocationReport->SetAltitudeError(altitudeerror);
|
|
}
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Print the GUID
|
|
SENSOR_ID SensorID;
|
|
hr = pLocationReport->GetSensorID(&SensorID);
|
|
PrintGUID(SensorID);
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Print the timestamp
|
|
SYSTEMTIME systime;
|
|
hr = pLocationReport->GetTimestamp(&systime);
|
|
PrintTime(systime);
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pLocationReport->QueryInterface(IID_PPV_ARGS(&spCivicAddressReport));
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
PrintCivicAddress(spCivicAddressReport);
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pLocationReport->QueryInterface(IID_PPV_ARGS(&spLatLongReport));
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
PrintLatLong(spLatLongReport);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
// Prints the fields of a civic address location report.
|
|
// Empty fields are not printed.
|
|
void PrintCivicAddress(ICivicAddressReport *pCivicAddressReport)
|
|
{
|
|
CComBSTR bstrAddress1;
|
|
CComBSTR bstrAddress2;
|
|
CComBSTR bstrPostalCode;
|
|
CComBSTR bstrCity;
|
|
CComBSTR bstrStateProvince;
|
|
CComBSTR bstrCountryRegion;
|
|
|
|
assert(pCivicAddressReport != NULL);
|
|
|
|
wprintf(L"\n\n");
|
|
|
|
HRESULT hr = pCivicAddressReport->GetAddressLine1(&bstrAddress1);
|
|
if (SUCCEEDED(hr) && (bstrAddress1.Length() != 0))
|
|
{
|
|
wprintf(L"\tAddress Line 1:\t%s\n", bstrAddress1);
|
|
}
|
|
hr = pCivicAddressReport->GetAddressLine2(&bstrAddress2);
|
|
if (SUCCEEDED(hr) && (bstrAddress2.Length() != 0))
|
|
{
|
|
wprintf(L"\tAddress Line 2:\t%s\n", bstrAddress2);
|
|
}
|
|
hr = pCivicAddressReport->GetPostalCode(&bstrPostalCode);
|
|
if (SUCCEEDED(hr) && (bstrPostalCode.Length() != 0))
|
|
{
|
|
wprintf(L"\tPostal Code:\t%s\n", bstrPostalCode);
|
|
}
|
|
hr = pCivicAddressReport->GetCity(&bstrCity);
|
|
if (SUCCEEDED(hr) && (bstrCity.Length() != 0))
|
|
{
|
|
wprintf(L"\tCity:\t\t%s\n", bstrCity);
|
|
}
|
|
hr = pCivicAddressReport->GetStateProvince(&bstrStateProvince);
|
|
if (SUCCEEDED(hr) && (bstrStateProvince.Length() != 0))
|
|
{
|
|
wprintf(L"\tState/Province:\t%s\n", bstrStateProvince);
|
|
}
|
|
hr = pCivicAddressReport->GetCountryRegion(&bstrCountryRegion);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Country/Region is an ISO-3166 two-letter or three-letter code.
|
|
wprintf(L"\tCountry/Region:\t%s\n\n", bstrCountryRegion);
|
|
}
|
|
}
|
|
|
|
// Prints the latitude and longitude from a latitude/longitude report
|
|
void PrintLatLong(ILatLongReport *pLatLongReport)
|
|
{
|
|
DOUBLE latitude;
|
|
DOUBLE longitude;
|
|
DOUBLE errorradius;
|
|
DOUBLE altitude;
|
|
DOUBLE altitudeerror;
|
|
|
|
assert(pLatLongReport != NULL);
|
|
|
|
wprintf(L"\n\n");
|
|
|
|
HRESULT hr = pLatLongReport->GetLatitude(&latitude);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
wprintf(L"\tLatitude:\t%lf\n", latitude);
|
|
}
|
|
hr = pLatLongReport->GetLongitude(&longitude);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
wprintf(L"\tLongitude:\t%lf\n", longitude);
|
|
}
|
|
hr = pLatLongReport->GetErrorRadius(&errorradius);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
wprintf(L"\tError Radius:\t%lf\n", errorradius);
|
|
}
|
|
hr = pLatLongReport->GetAltitude(&altitude);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
wprintf(L"\tAltitude:\t%lf\n", altitude);
|
|
}
|
|
hr = pLatLongReport->GetAltitudeError(&altitudeerror);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
wprintf(L"\tAltitude Error:\t%lf\n", altitudeerror);
|
|
}
|
|
}
|
|
|
|
// Prints a GUID in a friendly format.
|
|
void PrintGUID(REFGUID guid)
|
|
{
|
|
wprintf(L"\nThe GUID of the location provider is: ");
|
|
wchar_t szGUID[64];
|
|
StringFromGUID2(guid, szGUID, ARRAYSIZE(szGUID));
|
|
wprintf(szGUID);
|
|
}
|
|
|
|
// Prints the hour, minute, and second from a timestamp.
|
|
// The time is Coordinated Universal Time (UTC).
|
|
void PrintTime(const SYSTEMTIME st)
|
|
{
|
|
wprintf(L"\nThe report timestamp is M:%02d D:%02d %02d:%02d:%02d UTC\n", st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
|
|
}
|
|
|
|
// Helper function that strips the newline character
|
|
// from the line obtained by fgetws.
|
|
WCHAR * SafeGetws(wchar_t* dest, int size)
|
|
{
|
|
fgetws( dest, size, stdin);
|
|
int i = 0;
|
|
while (i < size)
|
|
{
|
|
if (dest[i] == L'\n')
|
|
{
|
|
dest[i] = '\0';
|
|
return dest;
|
|
}
|
|
i++;
|
|
}
|
|
return dest;
|
|
} |