Most of the currency variant conversion functions implemented.
Minor bugfixes and header tidying.

diff --git a/ole/variant.c b/ole/variant.c
index cdd58a5..7eaf58d 100644
--- a/ole/variant.c
+++ b/ole/variant.c
@@ -19,10 +19,12 @@
  *     working on this.
  */
  
+#include "wintypes.h"
 #include "oleauto.h"
 #include "heap.h"
 #include "debug.h"
 #include "winerror.h"
+#include "mapidefs.h"
 
 #include <string.h>
 #include <stdlib.h>
@@ -41,7 +43,7 @@
 static const unsigned long UI4_MAX = 4294967295;
 static const unsigned long UI4_MIN = 0;
 static const long I4_MAX = 2147483647;
-static const long I4_MIN = -2147483648.0;
+static const long I4_MIN = -2147483648;
 static const DATE DATE_MIN = -657434;
 static const DATE DATE_MAX = 2958465;
 
@@ -138,20 +140,18 @@
  */
 static double round( double d )
 {
-	double decimals = 0.0;
-	unsigned long integerValue = 0.0;
-    double roundedValue = 0.0;
+   double decimals = 0.0, integerValue = 0.0, roundedValue = 0.0;
     BOOL32 bEvenNumber = FALSE;
     int nSign = 0;
 
     /* Save the sign of the number
      */
-    nSign = d >= 0.0 ? 1 : -1;
+   nSign = (d >= 0.0) ? 1 : -1;
     d = fabs( d );
     
 	/* Remove the decimals.
 	 */
-	integerValue = (unsigned long) d;
+   integerValue = floor( d );
 
     /* Set the Even flag.  This is used to round the number when
      * the decimals are exactly 1/2.  If the integer part is
@@ -159,7 +159,7 @@
      * is even the number is rounded down.  Using this method
      * numbers are rounded up|down half the time.
      */
-    bEvenNumber = ((integerValue % 2) == 0) ? TRUE : FALSE;
+   bEvenNumber = (((short)fmod(integerValue, 2)) == 0) ? TRUE : FALSE;
 
     /* Remove the integral part of the number.
      */
@@ -198,7 +198,6 @@
 	return roundedValue * nSign;
 }
 
-
 /******************************************************************************
  *		RemoveCharacterFromString		[INTERNAL]
  *
@@ -535,7 +534,7 @@
 			res = VarI1FromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cVal) );
 			break;
 		case( VT_CY ):
-			/*res = VarI1FromCY32( ps->u.cyVal, &(pd->u.cVal) );*/
+	     res = VarI1FromCy32( ps->u.cyVal, &(pd->u.cVal) );
 		case( VT_DISPATCH ):
 			/*res = VarI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.cVal) );*/
 		case( VT_UNKNOWN ):
@@ -588,7 +587,7 @@
 			res = VarI2FromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.iVal) );
 			break;
 		case( VT_CY ):
-			/*res = VarI2FromCY32( ps->u.cyVal, &(pd->u.iVal) );*/
+	     res = VarI2FromCy32( ps->u.cyVal, &(pd->u.iVal) );
 		case( VT_DISPATCH ):
 			/*res = VarI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.iVal) );*/
 		case( VT_UNKNOWN ):
@@ -642,7 +641,7 @@
 			res = VarI4FromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.lVal) );
 			break;
 		case( VT_CY ):
-			/*res = VarI4FromCY32( ps->u.cyVal, &(pd->u.lVal) );*/
+	     res = VarI4FromCy32( ps->u.cyVal, &(pd->u.lVal) );
 		case( VT_DISPATCH ):
 			/*res = VarI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.lVal) );*/
 		case( VT_UNKNOWN ):
@@ -695,7 +694,7 @@
 			res = VarUI1FromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.bVal) );
 			break;
 		case( VT_CY ):
-			/*res = VarUI1FromCY32( ps->u.cyVal, &(pd->u.bVal) );*/
+	     res = VarUI1FromCy32( ps->u.cyVal, &(pd->u.bVal) );
 		case( VT_DISPATCH ):
 			/*res = VarUI1FromDisp32( ps->u.pdispVal, lcid, &(pd->u.bVal) );*/
 		case( VT_UNKNOWN ):
@@ -748,7 +747,7 @@
 			res = VarUI2FromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.uiVal) );
 			break;
 		case( VT_CY ):
-			/*res = VarUI2FromCY32( ps->u.cyVal, &(pd->u.uiVal) );*/
+	     res = VarUI2FromCy32( ps->u.cyVal, &(pd->u.uiVal) );
 		case( VT_DISPATCH ):
 			/*res = VarUI2FromDisp32( ps->u.pdispVal, lcid, &(pd->u.uiVal) );*/
 		case( VT_UNKNOWN ):
@@ -801,7 +800,7 @@
 			res = VarUI4FromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.ulVal) );
 			break;
 		case( VT_CY ):
-			/*res = VarUI4FromCY32( ps->u.cyVal, &(pd->u.ulVal) );*/
+	     res = VarUI4FromCy32( ps->u.cyVal, &(pd->u.ulVal) );
 		case( VT_DISPATCH ):
 			/*res = VarUI4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.ulVal) );*/
 		case( VT_UNKNOWN ):
@@ -854,7 +853,7 @@
 			res = VarR4FromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.fltVal) );
 			break;
 		case( VT_CY ):
-			/*res = VarR4FromCY32( ps->u.cyVal, &(pd->u.fltVal) );*/
+	     res = VarR4FromCy32( ps->u.cyVal, &(pd->u.fltVal) );
 		case( VT_DISPATCH ):
 			/*res = VarR4FromDisp32( ps->u.pdispVal, lcid, &(pd->u.fltVal) );*/
 		case( VT_UNKNOWN ):
@@ -907,7 +906,7 @@
 			res = VarR8FromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.dblVal) );
 			break;
 		case( VT_CY ):
-			/*res = VarR8FromCY32( ps->u.cyVal, &(pd->u.dblVal) );*/
+	     res = VarR8FromCy32( ps->u.cyVal, &(pd->u.dblVal) );
 		case( VT_DISPATCH ):
 			/*res = VarR8FromDisp32( ps->u.pdispVal, lcid, &(pd->u.dblVal) );*/
 		case( VT_UNKNOWN ):
@@ -964,7 +963,7 @@
 			res = VarDateFromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.date) );
 			break;
 		case( VT_CY ):
-			/*res = VarDateFromCY32( ps->u.cyVal, &(pd->u.date) );*/
+	     res = VarDateFromCy32( ps->u.cyVal, &(pd->u.date) );
 		case( VT_DISPATCH ):
 			/*res = VarDateFromDisp32( ps->u.pdispVal, lcid, &(pd->u.date) );*/
 		case( VT_UNKNOWN ):
@@ -1021,7 +1020,7 @@
 			res = VarBoolFromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.boolVal) );
 			break;
 		case( VT_CY ):
-			/*res = VarBoolFromCY32( ps->u.cyVal, &(pd->u.boolVal) );*/
+	     res = VarBoolFromCy32( ps->u.cyVal, &(pd->u.boolVal) );
 		case( VT_DISPATCH ):
 			/*res = VarBoolFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
 		case( VT_UNKNOWN ):
@@ -1078,7 +1077,7 @@
             res = VariantCopy32( pd, ps );
             break;
 		case( VT_CY ):
-			/*res = VarBstrFromCY32( ps->u.cyVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
+	     /*res = VarBstrFromCy32( ps->u.cyVal, lcid, dwFlags, &(pd->u.bstrVal) );*/
 		case( VT_DISPATCH ):
 			/*res = VarBstrFromDisp32( ps->u.pdispVal, lcid, lcid, dwFlags, &(pd->u.bstrVal) );*/
 		case( VT_UNKNOWN ):
@@ -1092,6 +1091,63 @@
 		}
 		break;
 
+     case( VT_CY ):
+	switch( vtFrom )
+	  {
+	  case( VT_I1 ):
+	     res = VarCyFromI132( ps->u.cVal, &(pd->u.cyVal) );
+	     break;
+	  case( VT_I2 ):
+	     res = VarCyFromI232( ps->u.iVal, &(pd->u.cyVal) );
+	     break;
+	  case( VT_INT ):
+	     res = VarCyFromInt32( ps->u.intVal, &(pd->u.cyVal) );
+	     break;
+	  case( VT_I4 ):
+	     res = VarCyFromI432( ps->u.lVal, &(pd->u.cyVal) );
+	     break;
+	  case( VT_UI1 ):
+	     res = VarCyFromUI132( ps->u.bVal, &(pd->u.cyVal) );
+	     break;
+	  case( VT_UI2 ):
+	     res = VarCyFromUI232( ps->u.uiVal, &(pd->u.cyVal) );
+	     break;
+	  case( VT_UINT ):
+	     res = VarCyFromUint32( ps->u.uintVal, &(pd->u.cyVal) );
+	     break;
+	  case( VT_UI4 ):
+	     res = VarCyFromUI432( ps->u.ulVal, &(pd->u.cyVal) );
+	     break;
+	  case( VT_R4 ):
+	     res = VarCyFromR432( ps->u.fltVal, &(pd->u.cyVal) );
+	     break;
+	  case( VT_R8 ):
+	     res = VarCyFromR832( ps->u.dblVal, &(pd->u.cyVal) );
+	     break;
+	  case( VT_DATE ):
+	     res = VarCyFromDate32( ps->u.date, &(pd->u.cyVal) );
+	     break;
+	  case( VT_BOOL ):
+	     res = VarCyFromBool32( ps->u.date, &(pd->u.cyVal) );
+	     break;
+	  case( VT_CY ):
+	     res = VariantCopy32( pd, ps );
+	     break;
+	  case( VT_BSTR ):
+	     /*res = VarCyFromStr32( ps->u.bstrVal, lcid, dwFlags, &(pd->u.cyVal) );*/
+	  case( VT_DISPATCH ):
+	     /*res = VarCyFromDisp32( ps->u.pdispVal, lcid, &(pd->u.boolVal) );*/
+	  case( VT_UNKNOWN ):
+	     /*res = VarCyFrom32( ps->u.lVal, &(pd->u.boolVal) );*/
+	  case( VT_DECIMAL ):
+	     /*res = VarCyFromDec32( ps->u.deiVal, &(pd->u.boolVal) );*/
+	  default:
+	     res = DISP_E_TYPEMISMATCH;
+	     FIXME(ole,"Coercion from %d to %d\n", vtFrom, vt );
+	     break;
+	  }
+	break;
+
 	default:
 		res = DISP_E_TYPEMISMATCH;
 		FIXME(ole,"Coercion from %d to %d\n", vtFrom, vt );
@@ -1367,7 +1423,7 @@
 					{
 						/* Prevent from cycling.  According to tests on
 						 * VariantCopyInd in Windows and the documentation
-						 * this API dereferences the inner Variants to only on depth.
+						 * this API dereferences the inner Variants to only one depth.
 						 * If the inner Variant itself contains an
 						 * other inner variant the E_INVALIDARG error is
 						 * returned. 
@@ -1707,6 +1763,19 @@
 	return S_OK;
 }
 
+/**********************************************************************
+ *              VarUI1FromCy32 [OLEAUT32.134]
+ * Convert currency to unsigned char
+ */
+HRESULT WINAPI VarUI1FromCy32(CY cyIn, BYTE* pbOut) {
+   double t = round((((double)cyIn.u.Hi * 4294967296) + (double)cyIn.u.Lo) / 10000);
+   
+   if (t > UI1_MAX || t < UI1_MIN) return DISP_E_OVERFLOW;
+   
+   *pbOut = (BYTE)t;
+   return S_OK;
+}
+
 /******************************************************************************
  *		VarI2FromUI132		[OLEAUT32.48]
  */
@@ -1900,6 +1969,19 @@
 	return S_OK;
 }
 
+/**********************************************************************
+ *              VarI2FromCy32 [OLEAUT32.52]
+ * Convert currency to signed short
+ */
+HRESULT WINAPI VarI2FromCy32(CY cyIn, short* psOut) {
+   double t = round((((double)cyIn.u.Hi * 4294967296) + (double)cyIn.u.Lo) / 10000);
+   
+   if (t > I2_MAX || t < I2_MIN) return DISP_E_OVERFLOW;
+   
+   *psOut = (SHORT)t;
+   return S_OK;
+}
+
 /******************************************************************************
  *		VarI4FromUI132		[OLEAUT32.58]
  */
@@ -2080,6 +2162,19 @@
 	return S_OK;
 }
 
+/**********************************************************************
+ *              VarI4FromCy32 [OLEAUT32.62]
+ * Convert currency to signed long
+ */
+HRESULT WINAPI VarI4FromCy32(CY cyIn, LONG* plOut) {
+   double t = round((((double)cyIn.u.Hi * 4294967296) + (double)cyIn.u.Lo) / 10000);
+   
+   if (t > I4_MAX || t < I4_MIN) return DISP_E_OVERFLOW;
+   
+   *plOut = (LONG)t;
+   return S_OK;
+}
+
 /******************************************************************************
  *		VarR4FromUI132		[OLEAUT32.68]
  */
@@ -2241,6 +2336,16 @@
 	return S_OK;
 }
 
+/**********************************************************************
+ *              VarR4FromCy32 [OLEAUT32.72]
+ * Convert currency to float
+ */
+HRESULT WINAPI VarR4FromCy32(CY cyIn, FLOAT* pfltOut) {
+   *pfltOut = (FLOAT)((((double)cyIn.u.Hi * 4294967296) + (double)cyIn.u.Lo) / 10000);
+   
+   return S_OK;
+}
+
 /******************************************************************************
  *		VarR8FromUI132		[OLEAUT32.68]
  */
@@ -2381,6 +2486,16 @@
 	return S_OK;
 }
 
+/**********************************************************************
+ *              VarR8FromCy32 [OLEAUT32.82]
+ * Convert currency to double
+ */
+HRESULT WINAPI VarR8FromCy32(CY cyIn, double* pdblOut) {
+   *pdblOut = (double)((((double)cyIn.u.Hi * 4294967296) + (double)cyIn.u.Lo) / 10000);
+   
+   return S_OK;
+}
+
 /******************************************************************************
  *		VarDateFromUI132		[OLEAUT32.]
  */
@@ -2554,6 +2669,16 @@
 	return S_OK;
 }
 
+/**********************************************************************
+ *              VarDateFromCy32 [OLEAUT32.93]
+ * Convert currency to date
+ */
+HRESULT WINAPI VarDateFromCy32(CY cyIn, DATE* pdateOut) {
+   *pdateOut = (DATE)((((double)cyIn.u.Hi * 4294967296) + (double)cyIn.u.Lo) / 10000);
+
+   if (*pdateOut > DATE_MAX || *pdateOut < DATE_MIN) return DISP_E_TYPEMISMATCH;
+   return S_OK;
+}
 
 /******************************************************************************
  *		VarBstrFromUI132		[OLEAUT32.108]
@@ -3050,6 +3175,17 @@
 	return S_OK;
 }
 
+/**********************************************************************
+ *              VarBoolFromCy32 [OLEAUT32.124]
+ * Convert currency to boolean
+ */
+HRESULT WINAPI VarBoolFromCy32(CY cyIn, VARIANT_BOOL* pboolOut) {
+      if (cyIn.u.Hi || cyIn.u.Lo) *pboolOut = -1;
+      else *pboolOut = 0;
+      
+      return S_OK;
+}
+
 /******************************************************************************
  *		VarI1FromUI132		[OLEAUT32.244]
  */
@@ -3243,6 +3379,19 @@
 	return S_OK;
 }
 
+/**********************************************************************
+ *              VarI1FromCy32 [OLEAUT32.250]
+ * Convert currency to signed char
+ */
+HRESULT WINAPI VarI1FromCy32(CY cyIn, CHAR* pcOut) {
+   double t = round((((double)cyIn.u.Hi * 4294967296) + (double)cyIn.u.Lo) / 10000);
+   
+   if (t > CHAR_MAX || t < CHAR_MIN) return DISP_E_OVERFLOW;
+   
+   *pcOut = (CHAR)t;
+   return S_OK;
+}
+
 /******************************************************************************
  *		VarUI2FromUI132		[OLEAUT32.257]
  */
@@ -3464,6 +3613,20 @@
 	return S_OK;
 }
 
+/**********************************************************************
+ *              VarUI2FromCy32 [OLEAUT32.263]
+ * Convert currency to unsigned short
+ */
+HRESULT WINAPI VarUI2FromCy32(CY cyIn, USHORT* pusOut) {
+   double t = round((((double)cyIn.u.Hi * 4294967296) + (double)cyIn.u.Lo) / 10000);
+   
+   if (t > UI2_MAX || t < UI2_MIN) return DISP_E_OVERFLOW;
+      
+   *pusOut = (USHORT)t;
+   
+   return S_OK;
+}
+
 /******************************************************************************
  *		VarUI4FromUI132		[OLEAUT32.270]
  */
@@ -3598,3 +3761,138 @@
 	return S_OK;
 }
 
+/**********************************************************************
+ *              VarUI4FromCy32 [OLEAUT32.276]
+ * Convert currency to unsigned long
+ */
+HRESULT WINAPI VarUI4FromCy32(CY cyIn, ULONG* pulOut) {
+   double t = round((((double)cyIn.u.Hi * 4294967296) + (double)cyIn.u.Lo) / 10000);
+   
+   if (t > UI4_MAX || t < UI4_MIN) return DISP_E_OVERFLOW;
+
+   *pulOut = (ULONG)t;
+
+   return S_OK;
+}
+
+/**********************************************************************
+ *              VarCyFromUI132 [OLEAUT32.98]
+ * Convert unsigned char to currency
+ */
+HRESULT WINAPI VarCyFromUI132(BYTE bIn, CY* pcyOut) {
+   pcyOut->u.Hi = 0;
+   pcyOut->u.Lo = ((ULONG)bIn) * 10000;
+   
+   return S_OK;
+}
+
+/**********************************************************************
+ *              VarCyFromI232 [OLEAUT32.99]
+ * Convert signed short to currency
+ */
+HRESULT WINAPI VarCyFromI232(short sIn, CY* pcyOut) {
+   if (sIn < 0) pcyOut->u.Hi = -1;
+   else pcyOut->u.Hi = 0;
+   pcyOut->u.Lo = ((ULONG)sIn) * 10000;
+   
+   return S_OK;
+}
+
+/**********************************************************************
+ *              VarCyFromI432 [OLEAUT32.100]
+ * Convert signed long to currency
+ */
+HRESULT WINAPI VarCyFromI432(LONG lIn, CY* pcyOut) {
+      double t = (double)lIn * (double)10000;
+      pcyOut->u.Hi = (LONG)(t / (double)4294967296);
+      pcyOut->u.Lo = (ULONG)fmod(t, (double)4294967296);
+      if (lIn < 0) pcyOut->u.Hi--;
+   
+      return S_OK;
+}
+
+/**********************************************************************
+ *              VarCyFromR432 [OLEAUT32.101]
+ * Convert float to currency
+ */
+HRESULT WINAPI VarCyFromR432(FLOAT fltIn, CY* pcyOut) {
+   double t = round((double)fltIn * (double)10000);
+   pcyOut->u.Hi = (LONG)(t / (double)4294967296);
+   pcyOut->u.Lo = (ULONG)fmod(t, (double)4294967296);
+   if (fltIn < 0) pcyOut->u.Hi--;
+   
+   return S_OK;
+}
+
+/**********************************************************************
+ *              VarCyFromR832 [OLEAUT32.102]
+ * Convert double to currency
+ */
+HRESULT WINAPI VarCyFromR832(double dblIn, CY* pcyOut) {
+   double t = round(dblIn * (double)10000);
+   pcyOut->u.Hi = (LONG)(t / (double)4294967296);
+   pcyOut->u.Lo = (ULONG)fmod(t, (double)4294967296);
+   if (dblIn < 0) pcyOut->u.Hi--;
+
+   return S_OK;
+}
+
+/**********************************************************************
+ *              VarCyFromDate32 [OLEAUT32.103]
+ * Convert date to currency
+ */
+HRESULT WINAPI VarCyFromDate32(DATE dateIn, CY* pcyOut) {
+   double t = round((double)dateIn * (double)10000);
+   pcyOut->u.Hi = (LONG)(t / (double)4294967296);
+   pcyOut->u.Lo = (ULONG)fmod(t, (double)4294967296);
+   if (dateIn < 0) pcyOut->u.Hi--;
+
+   return S_OK;
+}
+
+/**********************************************************************
+ *              VarCyFromBool32 [OLEAUT32.106]
+ * Convert boolean to currency
+ */
+HRESULT WINAPI VarCyFromBool32(VARIANT_BOOL boolIn, CY* pcyOut) {
+   if (boolIn < 0) pcyOut->u.Hi = -1;
+   else pcyOut->u.Hi = 0;
+   pcyOut->u.Lo = (ULONG)boolIn * (ULONG)10000;
+   
+   return S_OK;
+}
+
+/**********************************************************************
+ *              VarCyFromI132 [OLEAUT32.225]
+ * Convert signed char to currency
+ */
+HRESULT WINAPI VarCyFromI132(CHAR cIn, CY* pcyOut) {
+   if (cIn < 0) pcyOut->u.Hi = -1;
+   else pcyOut->u.Hi = 0;
+   pcyOut->u.Lo = (ULONG)cIn * (ULONG)10000;
+   
+   return S_OK;
+}
+
+/**********************************************************************
+ *              VarCyFromUI232 [OLEAUT32.226]
+ * Convert unsigned short to currency
+ */
+HRESULT WINAPI VarCyFromUI232(USHORT usIn, CY* pcyOut) {
+   pcyOut->u.Hi = 0;
+   pcyOut->u.Lo = (ULONG)usIn * (ULONG)10000;
+   
+   return S_OK;
+}
+
+/**********************************************************************
+ *              VarCyFromUI432 [OLEAUT32.227]
+ * Convert unsigned long to currency
+ */
+HRESULT WINAPI VarCyFromUI432(ULONG ulIn, CY* pcyOut) {
+   double t = (double)ulIn * (double)10000;
+   pcyOut->u.Hi = (LONG)(t / (double)4294967296);
+   pcyOut->u.Lo = (ULONG)fmod(t, (double)4294967296);
+      
+   return S_OK;
+}