diff --git a/GMap.NET.WindowsMobile/GMap.NET.GPS/GpsPosition.cs b/GMap.NET.WindowsMobile/GMap.NET.GPS/GpsPosition.cs
new file mode 100644
--- /dev/null
+++ b/GMap.NET.WindowsMobile/GMap.NET.GPS/GpsPosition.cs
@@ -0,0 +1,477 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//
+// Use of this sample source code is subject to the terms of the Microsoft
+// license agreement under which you licensed this sample source code. If
+// you did not accept the terms of the license agreement, you are not
+// authorized to use this sample source code. For the terms of the license,
+// please see the license agreement between you and Microsoft or, if applicable,
+// see the LICENSE.RTF on your install media or the root of your tools installation.
+// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
+//
+#region Using directives
+
+using System;
+using System.Runtime.InteropServices;
+using System.Collections;
+using System.Collections.Generic;
+
+#endregion
+
+namespace GMap.NET.GPS
+{
+ #region Internal Native Structures
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct SystemTime
+ {
+ internal short year;
+ internal short month;
+ internal short dayOfWeek;
+ internal short day;
+ internal short hour;
+ internal short minute;
+ internal short second;
+ internal short millisecond;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct SatelliteArray
+ {
+ int a, b, c, d, e, f, g, h, i, j, k, l;
+
+ public int Count
+ {
+ get
+ {
+ return 12;
+ }
+ }
+
+ public int this[int value]
+ {
+ get
+ {
+ if(value == 0)
+ return a;
+ else if(value == 1)
+ return b;
+ else if(value == 2)
+ return c;
+ else if(value == 3)
+ return d;
+ else if(value == 4)
+ return e;
+ else if(value == 5)
+ return f;
+ else if(value == 6)
+ return g;
+ else if(value == 7)
+ return h;
+ else if(value == 8)
+ return i;
+ else if(value == 9)
+ return j;
+ else if(value == 10)
+ return k;
+ else if(value == 11)
+ return l;
+ else
+ throw new ArgumentOutOfRangeException("value must be 0 - 11");
+ }
+ }
+ }
+ #endregion
+
+ public enum FixQuality : int
+ {
+ Unknown=0,
+ Gps,
+ DGps
+ }
+ public enum FixType : int
+ {
+ Unknown=0,
+ XyD,
+ XyzD
+ }
+
+ public enum FixSelection : int
+ {
+ Unknown=0,
+ Auto,
+ Manual
+ }
+
+ public struct Satellite
+ {
+ public Satellite(int id, int elevation, int azimuth, int signalStrength, bool inUse)
+ {
+ this.id = id;
+ this.elevation = elevation;
+ this.azimuth = azimuth;
+ this.signalStrength = signalStrength;
+ this.inUse = inUse;
+ }
+
+ bool inUse;
+ public bool InSolution
+ {
+ get
+ {
+ return inUse;
+ }
+ set
+ {
+ inUse = value;
+ }
+ }
+
+ int id;
+ ///
+ /// Id of the satellite
+ ///
+ public int Id
+ {
+ get
+ {
+ return id;
+ }
+ set
+ {
+ id = value;
+ }
+ }
+
+
+ int elevation;
+ ///
+ /// Elevation of the satellite
+ ///
+ public int Elevation
+ {
+ get
+ {
+ return elevation;
+ }
+ set
+ {
+ elevation = value;
+ }
+ }
+
+
+ int azimuth;
+ ///
+ /// Azimuth of the satellite
+ ///
+ public int Azimuth
+ {
+ get
+ {
+ return azimuth;
+ }
+ set
+ {
+ azimuth = value;
+ }
+ }
+
+
+ int signalStrength;
+ ///
+ /// SignalStrenth of the satellite
+ ///
+ public int SignalStrength
+ {
+ get
+ {
+ return signalStrength;
+ }
+ set
+ {
+ signalStrength = value;
+ }
+ }
+
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public class GpsPosition
+ {
+ internal GpsPosition()
+ {
+ }
+
+ internal static int GPS_VALID_UTC_TIME = 0x00000001;
+ internal static int GPS_VALID_LATITUDE = 0x00000002;
+ internal static int GPS_VALID_LONGITUDE = 0x00000004;
+ internal static int GPS_VALID_SPEED = 0x00000008;
+ internal static int GPS_VALID_HEADING = 0x00000010;
+ internal static int GPS_VALID_MAGNETIC_VARIATION = 0x00000020;
+ internal static int GPS_VALID_ALTITUDE_WRT_SEA_LEVEL = 0x00000040;
+ internal static int GPS_VALID_ALTITUDE_WRT_ELLIPSOID = 0x00000080;
+ internal static int GPS_VALID_POSITION_DILUTION_OF_PRECISION = 0x00000100;
+ internal static int GPS_VALID_HORIZONTAL_DILUTION_OF_PRECISION = 0x00000200;
+ internal static int GPS_VALID_VERTICAL_DILUTION_OF_PRECISION = 0x00000400;
+ internal static int GPS_VALID_SATELLITE_COUNT = 0x00000800;
+ internal static int GPS_VALID_SATELLITES_USED_PRNS = 0x00001000;
+ internal static int GPS_VALID_SATELLITES_IN_VIEW = 0x00002000;
+ internal static int GPS_VALID_SATELLITES_IN_VIEW_PRNS = 0x00004000;
+ internal static int GPS_VALID_SATELLITES_IN_VIEW_ELEVATION = 0x00008000;
+ internal static int GPS_VALID_SATELLITES_IN_VIEW_AZIMUTH = 0x00010000;
+ internal static int GPS_VALID_SATELLITES_IN_VIEW_SIGNAL_TO_NOISE_RATIO = 0x00020000;
+
+ internal int dwVersion = 1; // Current version of GPSID client is using.
+ internal int dwSize = 0; // sizeof(_GPS_POSITION)
+
+ // Not all fields in the structure below are guaranteed to be valid.
+ // Which fields are valid depend on GPS device being used, how stale the API allows
+ // the data to be, and current signal.
+ // Valid fields are specified in dwValidFields, based on GPS_VALID_XXX flags.
+ internal int dwValidFields = 0;
+
+ // Additional information about this location structure (GPS_DATA_FLAGS_XXX)
+ internal int dwFlags = 0;
+
+ //** Time related
+ internal SystemTime stUTCTime = new SystemTime(); // UTC according to GPS clock.
+
+ //** Position + heading related
+ internal double dblLatitude = 0.0; // Degrees latitude. North is positive
+ internal double dblLongitude = 0.0; // Degrees longitude. East is positive
+ internal float flSpeed = 0.0f; // Speed in knots
+ internal float flHeading = 0.0f; // Degrees heading (course made good). True North=0
+ internal double dblMagneticVariation = 0.0; // Magnetic variation. East is positive
+ internal float flAltitudeWRTSeaLevel = 0.0f; // Altitute with regards to sea level, in meters
+ internal float flAltitudeWRTEllipsoid = 0.0f; // Altitude with regards to ellipsoid, in meters
+
+ // Where did we get fix from?
+ internal FixQuality fixQuality = FixQuality.Unknown;
+
+ // Is this 2d or 3d fix?
+ internal FixType fixType = FixType.Unknown;
+
+ // Auto or manual selection between 2d or 3d mode
+ internal FixSelection selectionType = FixSelection.Unknown;
+
+ // Position Dilution Of Precision
+ internal float flPositionDilutionOfPrecision = 0.0f;
+
+ // Horizontal Dilution Of Precision
+ internal float flHorizontalDilutionOfPrecision = 0.0f;
+
+ // Vertical Dilution Of Precision
+ internal float flVerticalDilutionOfPrecision = 0.0f;
+
+ // Number of satellites used in solution
+ internal int dwSatelliteCount = 0;
+
+ // PRN numbers of satellites used in the solution
+ internal SatelliteArray rgdwSatellitesUsedPRNs = new SatelliteArray();
+
+ // Number of satellites in view. From 0-GPS_MAX_SATELLITES
+ internal int dwSatellitesInView = 0;
+
+ // PRN numbers of satellites in view
+ internal SatelliteArray rgdwSatellitesInViewPRNs = new SatelliteArray();
+
+ // Elevation of each satellite in view
+ internal SatelliteArray rgdwSatellitesInViewElevation = new SatelliteArray();
+
+ // Azimuth of each satellite in view
+ internal SatelliteArray rgdwSatellitesInViewAzimuth = new SatelliteArray();
+
+ // Signal to noise ratio of each satellite in view
+ internal SatelliteArray rgdwSatellitesInViewSignalToNoiseRatio = new SatelliteArray();
+
+ // ...
+
+ public FixQuality FixQuality
+ {
+ get
+ {
+ return fixQuality;
+ }
+ }
+
+ public FixType FixType
+ {
+ get
+ {
+ return fixType;
+ }
+ }
+
+ public FixSelection FixSelection
+ {
+ get
+ {
+ return selectionType;
+ }
+ }
+
+ ///
+ /// UTC according to GPS clock.
+ ///
+ public DateTime? Time
+ {
+ get
+ {
+ return ((dwValidFields & GPS_VALID_UTC_TIME) != 0) ? ((DateTime?) new DateTime(stUTCTime.year, stUTCTime.month, stUTCTime.day, stUTCTime.hour, stUTCTime.minute, stUTCTime.second, stUTCTime.millisecond)) : null;
+ }
+ }
+
+ ///
+ /// Satellites in view
+ ///
+ /// Array of Satellites
+ public IEnumerable GetSatellitesInView()
+ {
+ // if valid view
+ if((dwValidFields & GPS_VALID_SATELLITES_IN_VIEW) != 0 && dwSatellitesInView != 0)
+ {
+ for(int index = 0; index < dwSatellitesInView; index++)
+ {
+ Satellite ret = new Satellite(rgdwSatellitesInViewPRNs[index], rgdwSatellitesInViewElevation[index], rgdwSatellitesInViewAzimuth[index], rgdwSatellitesInViewSignalToNoiseRatio[index], false);
+
+ // if valid solution
+ if((dwValidFields & GPS_VALID_SATELLITES_USED_PRNS) != 0)
+ {
+ for(int index2 = 0; index2 < dwSatelliteCount; index2++)
+ {
+ if(rgdwSatellitesUsedPRNs[index2] == ret.Id)
+ {
+ ret.InSolution = true;
+ break;
+ }
+ }
+ }
+
+ yield return ret;
+ }
+ }
+ }
+
+ ///
+ /// Number of satellites used in solution
+ ///
+ public int? SatelliteCount
+ {
+ get
+ {
+ return (((dwValidFields & GPS_VALID_SATELLITE_COUNT) != 0) ? (int?) dwSatelliteCount : null);
+ }
+ }
+
+ ///
+ /// Number of satellites in view.
+ ///
+ public int? SatellitesInViewCount
+ {
+ get
+ {
+ return ((dwValidFields & GPS_VALID_SATELLITES_IN_VIEW) != 0) ? (int?) dwSatellitesInView : null;
+ }
+ }
+
+ ///
+ /// Speed in km/h
+ ///
+ public float? Speed
+ {
+ get
+ {
+ return ((dwValidFields & GPS_VALID_SPEED) != 0) ? (float?) (flSpeed*1.852f) : null;
+ }
+ }
+
+ ///
+ /// Altitude with regards to ellipsoid, in meters
+ ///
+ public float? EllipsoidAltitude
+ {
+ get
+ {
+ return ((dwValidFields & GPS_VALID_ALTITUDE_WRT_ELLIPSOID) != 0) ? (float?) flAltitudeWRTEllipsoid : null;
+ }
+ }
+
+ ///
+ /// Altitute with regards to sea level, in meters
+ ///
+ public float? SeaLevelAltitude
+ {
+ get
+ {
+ return ((dwValidFields & GPS_VALID_ALTITUDE_WRT_SEA_LEVEL) != 0) ? (float?) flAltitudeWRTSeaLevel : null;
+ }
+ }
+
+ ///
+ /// Latitude in decimal degrees. North is positive
+ ///
+ public double? Latitude
+ {
+ get
+ {
+ return ((dwValidFields & GPS_VALID_LATITUDE) != 0) ? (float?) dblLatitude : null;
+ }
+ }
+
+ ///
+ /// Longitude in decimal degrees. East is positive
+ ///
+ public double? Longitude
+ {
+ get
+ {
+ return ((dwValidFields & GPS_VALID_LONGITUDE) != 0) ? (float?) dblLongitude : null;
+ }
+ }
+
+ ///
+ /// Degrees heading (course made good). True North=0
+ ///
+ public float? Heading
+ {
+ get
+ {
+ return ((dwValidFields & GPS_VALID_HEADING) != 0) ? (float?) flHeading : null;
+ }
+ }
+
+ ///
+ /// Position Dilution Of Precision
+ ///
+ public float? PositionDilutionOfPrecision
+ {
+ get
+ {
+ return ((dwValidFields & GPS_VALID_POSITION_DILUTION_OF_PRECISION) != 0) ? (float?) flPositionDilutionOfPrecision : null;
+ }
+ }
+
+ ///
+ /// Horizontal Dilution Of Precision
+ ///
+ public float? HorizontalDilutionOfPrecision
+ {
+ get
+ {
+ return ((dwValidFields & GPS_VALID_HORIZONTAL_DILUTION_OF_PRECISION) != 0) ? (float?) flHorizontalDilutionOfPrecision : null;
+ }
+ }
+
+ ///
+ /// Vertical Dilution Of Precision
+ ///
+ public float? VerticalDilutionOfPrecision
+ {
+ get
+ {
+ return ((dwValidFields & GPS_VALID_VERTICAL_DILUTION_OF_PRECISION) != 0) ? (float?) flVerticalDilutionOfPrecision : null;
+ }
+ }
+ }
+}