diff --git a/src/attribute/attribute.c b/src/attribute/attribute.c
index 3c2ba6f4b0..ed923e5fe5 100644
--- a/src/attribute/attribute.c
+++ b/src/attribute/attribute.c
@@ -14,6 +14,179 @@
  * $HEADER$
  */
 
+/**
+ * @file
+ *
+ * Back-end MPI attribute engine.
+ *
+ * This is complicated enough that it deserves a lengthy discussion of
+ * what is happening.  This is extremely complicated stuff, paired
+ * with the fact that it is not described well in the MPI standard.
+ * There are several places in the standard that should be read about
+ * attributes:
+ *
+ * MPI-1: Section 5.7 (pp 167-173)
+ * MPI-1: Section 7.1 (pp 191-192) predefined attributes in MPI-1
+ * MPI-2: Section 4.12.7 (pp 57-59) interlanguage attribute
+ *        clarifications
+ * MPI-2: Section 6.2.2 (pp 112) window predefined attributes
+ * MPI-2: Section 8.8 (pp 198-208) new attribute caching functions
+ *
+ * After reading all of this, note the following:
+ *
+ * - C MPI-1 and MPI-2 attribute functions and functionality are
+ *   identical except for their function names.
+ * - Fortran MPI-1 and MPI-2 attribute functions and functionality are
+ *   different (namely: the parameters are different sizes, both in the
+ *   functions and the user callbacks, and the assignments to the
+ *   different sized types occur differently [e.g., truncation and sign
+ *   extension])
+ * - C functions store values by reference (i.e., writing an attribute
+ *   means writing a pointer to an instance of something; changing the
+ *   value of that instance will make it visible to anyone who reads
+ *   that attribute value).
+ * - Fortran functions store values by value (i.e., writing an
+ *   attribute value means that anyone who reads that attribute value
+ *   will not be able to affect the value read by anyone else).
+ * - The predefined attribute MPI_WIN_BASE seems to flaunt the rules
+ *   designated by the rest of the standard; it is handled
+ *   specifically in the MPI_WIN_GET_ATTR binding functions (see the 
+ *   comments in there for an explanation).
+ * - MPI-2 4.12.7:Example 4.13 (p58) is wrong.  The C->Fortran example
+ *   should have the Fortran "val" variable equal to &I.
+ *
+ * By the first two of these, there are 9 possible use cases -- 3
+ * possibilities for writing an attribute value, each of which has 3
+ * possibilities for reading that value back.  The following lists
+ * each of the 9 cases, and what happens in each.
+ *
+ * Cases where C writes an attribute value:
+ * ----------------------------------------
+ *
+ * In all of these cases, a pointer was written by C (e.g., a pointer
+ * to an int -- but it could have been a pointer to anything, such as
+ * a struct).  These scenarios each have 2 examples:
+ *
+ * Example A: int foo = 3; 
+ *            MPI_Attr_put(..., &foo);
+ * Example B: struct foo bar; 
+ *            MPI_Attr_put(..., &bar);
+ * 
+ * 1. C reads the attribute value.  Clearly, this is a "unity" case,
+ * and no translation occurs.  A pointer is written, and that same
+ * pointer is returned.
+ *
+ * Example A: int *ret; 
+ *            MPI_Attr_get(..., &ret); 
+ *            --> *ret will equal 3
+ * Example B: struct foo *ret; 
+ *            MPI_Attr_get(..., &ret);
+ *            --> *ret will point to the instance bar that was written
+ *
+ * 2. Fortran MPI-1 reads the attribute value.  The C pointer is cast
+ * to a fortran INTEGER (i.e., MPI_Fint) -- potentially being
+ * truncated if sizeof(void*) > sizeof(INTEGER).
+ *
+ * Example A: INTEGER ret
+ *            CALL MPI_ATTR_GET(..., ret, ierr)
+ *            --> ret will equal &foo, possibly truncaed
+ * Example B: INTEGER ret
+ *            CALL MPI_ATTR_GET(..., ret, ierr)
+ *            --> ret will equal &bar, possibly truncaed
+ *
+ * 3. Fortran MPI-2 reads the attribute value.  The C pointer is cast
+ * to a fortran INTEGER(KIND=MPI_ADDRESS_KIND) (i.e., a (MPI_Aint)).
+ *
+ * Example A: INTEGER(KIND=MPI_ADDRESS_KIND) ret
+ *            CALL MPI_COMM_GET_ATTR(..., ret, ierr)
+ *            --> ret will equal &foo
+ * Example B: INTEGER(KIND=MPI_ADDRESS_KIND) ret
+ *            CALL MPI_COMM_GET_ATTR(..., ret, ierr) 
+ *            --> ret will equal &bar
+ *
+ * Cases where Fortran MPI-1 writes an attribute value:
+ * ----------------------------------------------------
+ *
+ * In all of these cases, an INTEGER is written by Fortran.
+ *
+ * Example: INTEGER FOO = 7
+ *          CALL MPI_ATTR_PUT(..., foo, ierr)
+ *
+ * 4. C reads the attribute value.  The value returned is a pointer
+ *    that points to an INTEGER (i.e., an MPI_Fint) that has a value
+ *    of 7.
+ *    --> NOTE: The external MPI interface does not distinguish between
+ *        this case and case 7.  It is the programer's responsibility
+ *        to code accordingly.
+ *
+ * Example: MPI_Fint *ret; 
+ *          MPI_Attr_get(..., &ret);
+ *          -> *ret will equal 7.
+ *
+ * 5. Fortran MPI-1 reads the attribute value.  This is the unity
+ *    case; the same value is returned.
+ *
+ * Example: INTEGER ret
+ *          CALL MPI_ATTR_GET(..., ret, ierr)
+ *          --> ret will equal 7
+ *
+ * 6. Fortran MPI-2 reads the attribute value.  The same value is
+ *    returned, but potentially sign-extended if sizeof(INTEGER) <
+ *    sizeof(INTEGER(KIND=MPI_ADDRESS_KIND)).
+ *
+ * Example: INTEGER(KIND=MPI_ADDRESS_KIND) ret
+ *          CALL MPI_COMM_GET_ATTR(..., ret, ierr)
+ *          --> ret will equal 7
+ *
+ * Cases where Fortran MPI-2 writes an attribute value:
+ * ----------------------------------------------------
+ *
+ * In all of these cases, an INTEGER(KIND=MPI_ADDRESS_KIND) is written
+ * by Fortran.
+ *
+ * Example A: INTEGER(KIND=MPI_ADDRESS_KIND) FOO = 12
+ *            CALL MPI_COMM_PUT_ATTR(..., foo, ierr)
+ * Example B: // Assume a platform where sizeof(void*) = 8 and
+ *            // sizeof(INTEGER) = 4.
+ *            INTEGER(KIND=MPI_ADDRESS_KIND) FOO = pow(2, 40)
+ *            CALL MPI_COMM_PUT_ATTR(..., foo, ierr)
+ *
+ * 7. C reads the attribute value.  The value returned is a pointer
+ *    that points to an INTEGER(KIND=MPI_ADDRESS_KIND) (i.e., a void*)
+ *    that has a value of 12.
+ *    --> NOTE: The external MPI interface does not distinguish between
+ *        this case and case 4.  It is the programer's responsibility
+ *        to code accordingly.
+ *
+ * Example A: MPI_Aint *ret; 
+ *            MPI_Attr_get(..., &ret);
+ *            -> *ret will equal 12
+ * Example B: MPI_Aint *ret; 
+ *            MPI_Attr_get(..., &ret);
+ *            -> *ret will equal 2^40
+ *
+ * 8. Fortran MPI-1 reads the attribute value.  The same value is
+ *    returned, but potentially truncated if sizeof(INTEGER) <
+ *    sizeof(INTEGER(KIND=MPI_ADDRESS_KIND)).
+ *
+ * Example A: INTEGER ret
+ *            CALL MPI_ATTR_GET(..., ret, ierr)
+ *            --> ret will equal 12
+ * Example B: INTEGER ret
+ *            CALL MPI_ATTR_GET(..., ret, ierr)
+ *            --> ret will equal 0
+ *
+ * 9. Fortran MPI-2 reads the attribute value.  This is the unity
+ *    case; the same value is returned.
+ *
+ * Example A: INTEGER(KIND=MPI_ADDRESS_KIND) ret
+ *            CALL MPI_COMM_GET_ATTR(..., ret, ierr)
+ *            --> ret will equal 7
+ * Example B: INTEGER(KIND=MPI_ADDRESS_KIND) ret
+ *            CALL MPI_COMM_GET_ATTR(..., ret, ierr)
+ *            --> ret will equal 2^40
+ */
+
 #include "ompi_config.h"
 
 #include "attribute/attribute.h"
@@ -54,10 +227,10 @@
 
    1. MPI-1 Fortran-style: attribute and extra state arguments are of
       type (INTEGER).  This is used if both the OMPI_KEYVAL_F77 and
-      OMPI_KEYVAL_F77_OLD flags are set.
+      OMPI_KEYVAL_F77_MPI1 flags are set.
    2. MPI-2 Fortran-style: attribute and extra state arguments are of
       type (INTEGER(KIND=MPI_ADDRESS_KIND)).  This is used if the
-      OMPI_KEYVAL_F77 flag is set and the OMPI_KEYVAL_F77_OLD flag is
+      OMPI_KEYVAL_F77 flag is set and the OMPI_KEYVAL_F77_MPI1 flag is
       *not* set.
    3. C-style: attribute arguments are of type (void*).  This is used
       if OMPI_KEYVAL_F77 is not set.
@@ -65,17 +238,16 @@
    Ick.
  */
 
-#define DELETE_ATTR_OBJECT(type, attribute, keyval_obj) \
+#define DELETE_ATTR_CALLBACKS(type, attribute, keyval_obj) \
     if (0 != (keyval_obj->attr_flag & OMPI_KEYVAL_F77)) { \
         MPI_Fint f_key = OMPI_INT_2_FINT(key); \
         MPI_Fint f_err; \
         /* MPI-1 Fortran-style */ \
-        if (0 != (keyval_obj->attr_flag & OMPI_KEYVAL_F77_OLD)) { \
-            ompi_attribute_fortran_ptr_t value; \
-            value.c_ptr = attribute; \
+        if (0 != (keyval_obj->attr_flag & OMPI_KEYVAL_F77_MPI1)) { \
+            MPI_Fint attr_val = translate_to_fortran_mpi1(attribute); \
             (*((keyval_obj->delete_attr_fn).attr_mpi1_fortran_delete_fn)) \
                 (&(((ompi_##type##_t *)object)->attr_##type##_f), \
-                 &f_key, &value.f_integer, keyval_obj->extra_state, &f_err); \
+                 &f_key, &attr_val, keyval_obj->extra_state, &f_err); \
             if (MPI_SUCCESS != OMPI_FINT_2_INT(f_err)) { \
                 if (need_lock) { \
                     OMPI_THREAD_UNLOCK(&alock); \
@@ -85,9 +257,10 @@
         } \
         /* MPI-2 Fortran-style */ \
         else { \
+            MPI_Aint attr_val = translate_to_fortran_mpi2(attribute); \
             (*((keyval_obj->delete_attr_fn).attr_mpi2_fortran_delete_fn)) \
                 (&(((ompi_##type##_t *)object)->attr_##type##_f), \
-                 &f_key, &attribute, keyval_obj->extra_state, &f_err); \
+                 &f_key, &attr_val, keyval_obj->extra_state, &f_err); \
             if (MPI_SUCCESS != OMPI_FINT_2_INT(f_err)) { \
                 if (need_lock) { \
                     OMPI_THREAD_UNLOCK(&alock); \
@@ -98,9 +271,10 @@
     } \
     /* C style */ \
     else { \
+        void *attr_val = translate_to_c(attribute); \
         if ((err = (*((keyval_obj->delete_attr_fn).attr_##type##_delete_fn)) \
                             ((ompi_##type##_t *)object, \
-			    key, attribute, \
+			    key, attr_val, \
 			    keyval_obj->extra_state)) != MPI_SUCCESS) {\
             if (need_lock) { \
                 OMPI_THREAD_UNLOCK(&alock); \
@@ -109,73 +283,110 @@
         } \
     }
 
-/* See the big, long comment above from DELETE_ATTR_OBJECT -- most of
+/* See the big, long comment above from DELETE_ATTR_CALLBACKS -- most of
    that text applies here, too. */
 
-#define COPY_ATTR_OBJECT(type, old_object, keyval_obj, in_attr, out_attr) \
+#define COPY_ATTR_CALLBACKS(type, old_object, keyval_obj, in_attr, out_attr) \
     if (0 != (keyval_obj->attr_flag & OMPI_KEYVAL_F77)) { \
         MPI_Fint f_key = OMPI_INT_2_FINT(key); \
         MPI_Fint f_err; \
         ompi_fortran_logical_t f_flag; \
         /* MPI-1 Fortran-style */ \
-        if (0 != (keyval_obj->attr_flag & OMPI_KEYVAL_F77_OLD)) { \
-            ompi_attribute_fortran_ptr_t in, out; \
-            MPI_Fint tmp = 0; \
-            in.c_ptr = in_attr; \
+        if (0 != (keyval_obj->attr_flag & OMPI_KEYVAL_F77_MPI1)) { \
+            MPI_Fint in, out; \
+            in = translate_to_fortran_mpi1(in_attr); \
             (*((keyval_obj->copy_attr_fn).attr_mpi1_fortran_copy_fn)) \
-                (&(((ompi_##type##_t *)old_object)->attr_##type##_f),\
+                (&(((ompi_##type##_t *)old_object)->attr_##type##_f), \
                  &f_key, keyval_obj->extra_state, \
-                 &in.f_integer, &tmp, &f_flag, &f_err); \
+                 &in, &out, &f_flag, &f_err); \
             if (MPI_SUCCESS != OMPI_FINT_2_INT(f_err)) { \
                 OMPI_THREAD_UNLOCK(&alock); \
                 return OMPI_FINT_2_INT(f_err); \
             } \
-            /* Must do weird sign extension -- see src/mpi/f77/attr_put_f.c for details */ \
-            if (tmp < 0) { \
-                out.c_ptr = (void *) -1; \
-            } else { \
-                out.c_ptr = (void *) 0; \
-            } \
-            out.f_integer = tmp; \
-            out_attr = out.c_ptr; \
+            out_attr->av_value = (void *) out; \
             flag = OMPI_FINT_2_INT(f_flag); \
         } \
         /* MPI-2 Fortran-style */ \
         else { \
+            MPI_Aint in, out; \
+            in = translate_to_fortran_mpi2(in_attr); \
             (*((keyval_obj->copy_attr_fn).attr_mpi2_fortran_copy_fn)) \
                 (&(((ompi_##type##_t *)old_object)->attr_##type##_f), \
-                 &f_key, keyval_obj->extra_state, &in_attr, &out_attr, \
+                 &f_key, keyval_obj->extra_state, &in, &out, \
                  &f_flag, &f_err); \
             if (MPI_SUCCESS != OMPI_FINT_2_INT(f_err)) { \
                 OMPI_THREAD_UNLOCK(&alock); \
                 return OMPI_FINT_2_INT(f_err); \
             } \
+            out_attr->av_value = (void *) out; \
             flag = OMPI_FINT_2_INT(f_flag); \
         } \
     } \
     /* C style */ \
     else { \
+        void *in, *out; \
+        in = translate_to_c(in_attr); \
         if ((err = (*((keyval_obj->copy_attr_fn).attr_##type##_copy_fn)) \
               ((ompi_##type##_t *)old_object, key, keyval_obj->extra_state, \
-               in_attr, &out_attr, &flag)) != MPI_SUCCESS) { \
+               in, &out, &flag)) != MPI_SUCCESS) { \
             OMPI_THREAD_UNLOCK(&alock); \
             return err; \
         } \
+        out_attr->av_value = out; \
     }
 
 
 /* 
- * Static
+ * Cases for attribute values
  */
+typedef enum ompi_attribute_translate_t {
+    OMPI_ATTRIBUTE_C,
+    OMPI_ATTRIBUTE_FORTRAN_MPI1,
+    OMPI_ATTRIBUTE_FORTRAN_MPI2
+} ompi_attribute_translate_t;
+
+
+/*
+ * struct to hold attribute values on each MPI object
+ */
+typedef struct attribute_value_t {
+    ompi_object_t super;
+    void *av_value;
+    void *av_address_kind_pointer;
+    void *av_integer_pointer;
+    int av_set_from;
+} attribute_value_t;
+
+
+/* 
+ * Local functions
+ */
+static void attribute_value_construct(attribute_value_t *item);
 static void ompi_attrkey_item_construct(ompi_attrkey_item_t *item);
 static void ompi_attrkey_item_destruct(ompi_attrkey_item_t *item);
+static int set_value(ompi_attribute_type_t type, void *object, 
+                     ompi_hash_table_t **keyhash, int key, 
+                     attribute_value_t *new_attr,
+                     bool predefined, bool need_lock);
+static int get_value(ompi_hash_table_t *keyhash, int key, 
+                     attribute_value_t **attribute, int *flag);
+static void *translate_to_c(attribute_value_t *val);
+static MPI_Fint translate_to_fortran_mpi1(attribute_value_t *val);
+static MPI_Aint translate_to_fortran_mpi2(attribute_value_t *val);
+
+
+/*
+ * attribute_value_t class
+ */
+static OBJ_CLASS_INSTANCE(attribute_value_t,
+                          ompi_object_t,
+                          attribute_value_construct,
+                          NULL);
 
 
 /*
  * ompi_attribute_entry_t classes
  */
-
-struct ompi_attrkey_item_t_class;
 static OBJ_CLASS_INSTANCE(ompi_attrkey_item_t, 
                           ompi_object_t,
                           ompi_attrkey_item_construct,
@@ -188,6 +399,7 @@ static OBJ_CLASS_INSTANCE(ompi_attrkey_item_t,
 
 static ompi_hash_table_t *keyval_hash;
 static ompi_bitmap_t *key_bitmap;
+static unsigned int int_pos = 12345;
 
 #if OMPI_HAVE_THREAD_SUPPORT
 /*
@@ -201,10 +413,21 @@ static ompi_bitmap_t *key_bitmap;
 static ompi_mutex_t alock;
 #endif  /* OMPI_HAVE_THREAD_SUPPORT */
 
-/*
- * ompi_attrkey_item_t interface functions
- */
 
+/*
+ * attribute_value_t constructor function
+ */
+static void attribute_value_construct(attribute_value_t *item)
+{
+    item->av_address_kind_pointer = &item->av_value;
+    item->av_integer_pointer = &(((MPI_Fint*) &item->av_value)[int_pos]);
+    item->av_set_from = 0;
+}
+
+
+/*
+ * ompi_attrkey_item_t constructor / destructor
+ */
 static void
 ompi_attrkey_item_construct(ompi_attrkey_item_t *item) 
 {
@@ -230,20 +453,28 @@ ompi_attrkey_item_destruct(ompi_attrkey_item_t *item)
  * items. This will be called one time, mostly during MPI_INIT()
  */
 
-int 
-ompi_attr_init(void)
+int ompi_attr_init(void)
 {
     int ret;
+    void *bogus = (void*) 1;
+    MPI_Fint *p = (MPI_Fint*) &bogus;
 
     keyval_hash = OBJ_NEW(ompi_hash_table_t);
     if (NULL == keyval_hash) {
-        /* show_help */
 	return MPI_ERR_SYSRESOURCE;
     }
     key_bitmap = OBJ_NEW(ompi_bitmap_t);
     if (0 != ompi_bitmap_init(key_bitmap, 10)) {
 	return MPI_ERR_SYSRESOURCE;
     }
+
+    for (int_pos = 0; int_pos < (sizeof(void*) / sizeof(MPI_Fint)); 
+         ++int_pos) {
+        if (p[int_pos] == 1) {
+            break;
+        }
+    }
+
     if (OMPI_SUCCESS != (ret = ompi_hash_table_init(keyval_hash,
                                                     ATTR_TABLE_SIZE))) {
 	return ret;
@@ -260,8 +491,7 @@ ompi_attr_init(void)
  * This will destroy the list, mostly during MPI_Finalize()
  */
 
-int
-ompi_attr_finalize(void)
+int ompi_attr_finalize(void)
 {
     OBJ_RELEASE(keyval_hash);
     OBJ_RELEASE(key_bitmap);
@@ -270,11 +500,10 @@ ompi_attr_finalize(void)
 }
   
 
-int 
-ompi_attr_create_keyval(ompi_attribute_type_t type,
-			ompi_attribute_fn_ptr_union_t copy_attr_fn,
-			ompi_attribute_fn_ptr_union_t delete_attr_fn,
-			int *key, void *extra_state, int flags)
+int ompi_attr_create_keyval(ompi_attribute_type_t type,
+                            ompi_attribute_fn_ptr_union_t copy_attr_fn,
+                            ompi_attribute_fn_ptr_union_t delete_attr_fn,
+                            int *key, void *extra_state, int flags)
 {
     ompi_attrkey_item_t *attr;
     int ret;
@@ -319,8 +548,8 @@ ompi_attr_create_keyval(ompi_attribute_type_t type,
 }
 
 
-int 
-ompi_attr_free_keyval(ompi_attribute_type_t type, int *key, bool predefined)
+int ompi_attr_free_keyval(ompi_attribute_type_t type, int *key, 
+                          bool predefined)
 {
     int ret;
     ompi_attrkey_item_t *key_item;
@@ -338,7 +567,8 @@ ompi_attr_free_keyval(ompi_attribute_type_t type, int *key, bool predefined)
 					   (void **) &key_item);
     OMPI_THREAD_UNLOCK(&alock);
   
-    if ((OMPI_SUCCESS != ret) || (NULL == key_item) || (key_item->attr_type != type) ||
+    if ((OMPI_SUCCESS != ret) || (NULL == key_item) || 
+        (key_item->attr_type != type) ||
 	((!predefined) && (key_item->attr_flag & OMPI_KEYVAL_PREDEFINED))) {
 	return OMPI_ERR_BAD_PARAM;
     }
@@ -357,14 +587,13 @@ ompi_attr_free_keyval(ompi_attribute_type_t type, int *key, bool predefined)
 }
 
 
-int 
-ompi_attr_delete(ompi_attribute_type_t type, void *object, 
-                 ompi_hash_table_t *keyhash, int key,
-                 bool predefined, bool need_lock) 
+int ompi_attr_delete(ompi_attribute_type_t type, void *object, 
+                     ompi_hash_table_t *keyhash, int key,
+                     bool predefined, bool need_lock) 
 {
     ompi_attrkey_item_t *key_item;
     int ret = OMPI_SUCCESS, err;
-    void *attr;
+    attribute_value_t *attr;
 
     /* Protect against the user calling ompi_attr_destroy and then
        calling any of the functions which use it  */
@@ -382,12 +611,13 @@ ompi_attr_delete(ompi_attribute_type_t type, void *object,
         OMPI_THREAD_LOCK(&alock);
     }
 
-    /* Check if the key is valid in the key-attribute hash */
+    /* Check if the key is valid in the master keyval hash */
 
     ret = ompi_hash_table_get_value_uint32(keyval_hash, key, 
 					   (void **) &key_item);
 
-    if ( (OMPI_SUCCESS != ret)||(NULL == key_item)||(key_item->attr_type!= type)||
+    if ((OMPI_SUCCESS != ret) || (NULL == key_item) ||
+        (key_item->attr_type!= type) ||
 	((!predefined) && (key_item->attr_flag & OMPI_KEYVAL_PREDEFINED))) {
 	ret = OMPI_ERR_BAD_PARAM;
 	goto exit;
@@ -401,31 +631,31 @@ ompi_attr_delete(ompi_attribute_type_t type, void *object,
     }
 
     /* Check if the key is valid for the communicator/window/dtype. If
-       yes, then delete the attribute and key entry from the CWD hash */
+       yes, then delete the attribute and key entry from the object's key
+       hash */
 
-    ret = ompi_hash_table_get_value_uint32(keyhash, key, &attr);
-
-    if ( OMPI_SUCCESS == ret ) {
-	switch(type) {
-	    case COMM_ATTR:
-		DELETE_ATTR_OBJECT(communicator, attr, key_item);
-		break;
+    ret = ompi_hash_table_get_value_uint32(keyhash, key, (void**) &attr);
+    if (OMPI_SUCCESS == ret) {
+	switch (type) {
+        case COMM_ATTR:
+            DELETE_ATTR_CALLBACKS(communicator, attr, key_item);
+            break;
 		
 #if OMPI_WANT_MPI2_ONE_SIDED
-	    case WIN_ATTR:
-		DELETE_ATTR_OBJECT(win, attr, key_item);
-		break;
+        case WIN_ATTR:
+            DELETE_ATTR_CALLBACKS(win, attre, key_item);
+            break;
 #endif
 		
-	    case TYPE_ATTR:
-		DELETE_ATTR_OBJECT(datatype, attr, key_item);
-		break;
+        case TYPE_ATTR:
+            DELETE_ATTR_CALLBACKS(datatype, attr, key_item);
+            break;
 		
-	    default:
-		/* show_help */
-		ret = MPI_ERR_INTERN;
-		goto exit;
+        default:
+            ret = MPI_ERR_INTERN;
+            goto exit;
 	}
+        OBJ_RELEASE(attr);
     
 	ret = ompi_hash_table_remove_value_uint32(keyhash, key);
 	if (OMPI_SUCCESS != ret) {
@@ -448,151 +678,138 @@ ompi_attr_delete(ompi_attribute_type_t type, void *object,
 }
 
 
-int
-ompi_attr_set(ompi_attribute_type_t type, void *object, 
-              ompi_hash_table_t **keyhash, int key, void *attribute,
-              bool predefined, bool need_lock)
+/*
+ * Front-end function called by the C MPI API functions to set an
+ * attribute.
+ */
+int ompi_attr_set_c(ompi_attribute_type_t type, void *object, 
+                    ompi_hash_table_t **keyhash,
+                    int key, void *attribute, bool predefined, bool need_lock)
 {
-    ompi_attrkey_item_t *key_item;
-    int ret, err;
-    void *oldattr;
-    bool had_old = false;
-
-    /* Protect against the user calling ompi_attr_destroy and then
-       calling any of the functions which use it  */
-    if (NULL == keyval_hash) {
-	return MPI_ERR_INTERN;
-    }
-    if (NULL == keyhash) {
-        return MPI_ERR_INTERN;
+    attribute_value_t *new_attr = OBJ_NEW(attribute_value_t);
+    if (NULL == new_attr) {
+        return MPI_ERR_SYSRESOURCE;
     }
 
-    /* Note that this function can be invoked by ompi_attr_copy_all()
-       to set attributes on the new object (in addition to the
-       top-level MPI_* functions that set attributes).  In these
-       cases, ompi_attr_copy_all() has already locked the keyval_lock,
-       so we should not try to lock it again. */
-
-    if (need_lock) {
-        OMPI_THREAD_LOCK(&alock);
-    }
-    ret = ompi_hash_table_get_value_uint32(keyval_hash, key, 
-					   (void **) &key_item);
-
-    /* If key not found */
-
-    if ( (OMPI_SUCCESS != ret )||(NULL == key_item) || (key_item->attr_type != type) ||
-	((!predefined) && (key_item->attr_flag & OMPI_KEYVAL_PREDEFINED))) {
-        if (need_lock) {
-            OMPI_THREAD_UNLOCK(&alock);
-        }
-	return OMPI_ERR_BAD_PARAM;
-    }
-
-    /* Do we need to make a new keyhash? */
-
-    if (NULL == *keyhash) {
-        ompi_attr_hash_init(keyhash);
-    }
-
-    /* Now see if the key is present in the CWD object. If so, delete
-       the old attribute in the key */
-
-    ret = ompi_hash_table_get_value_uint32(*keyhash, key, &oldattr);
-    if ( OMPI_SUCCESS == ret )  {
-	switch(type) {
-	case COMM_ATTR:
-	    DELETE_ATTR_OBJECT(communicator, oldattr, key_item);
-	    break;
-
-#if OMPI_WANT_MPI2_ONE_SIDED
-	case WIN_ATTR:
-	    DELETE_ATTR_OBJECT(win, oldattr, key_item);
-	    break;
-#endif
-
-	case TYPE_ATTR:	    
-	    DELETE_ATTR_OBJECT(datatype, oldattr, key_item);
-	    break;
-
-	default:
-            /* show_help */
-            return MPI_ERR_INTERN;
-	}
-	had_old = true;
-    }
-
-    ret = ompi_hash_table_set_value_uint32(*keyhash, key, attribute); 
-    if (need_lock) {
-        OMPI_THREAD_UNLOCK(&alock);
-    }
-    if (OMPI_SUCCESS != ret) {
-	return ret; 
-    }
-
-    /* Increase the reference count of the object, only if there was no
-       old atribute/no old entry in the CWD */
-
-    if (!had_old) {
-	OBJ_RETAIN(key_item);
-    }
-    return MPI_SUCCESS;
+    new_attr->av_value = attribute;
+    new_attr->av_set_from = OMPI_ATTRIBUTE_C;
+    return set_value(type, object, keyhash, key, new_attr,
+                     predefined, need_lock);
 }
 
 
-int
-ompi_attr_get(ompi_hash_table_t *keyhash, int key, void *attribute,
-              int *flag)
+/*
+ * Front-end function called by the Fortran MPI-2 API functions to set
+ * an attribute.
+ */
+int ompi_attr_set_fortran_mpi1(ompi_attribute_type_t type, void *object, 
+                               ompi_hash_table_t **keyhash,
+                               int key, MPI_Fint attribute, 
+                               bool predefined, bool need_lock)
 {
+    attribute_value_t *new_attr = OBJ_NEW(attribute_value_t);
+    if (NULL == new_attr) {
+        return MPI_ERR_SYSRESOURCE;
+    }
+
+    new_attr->av_value = (void *) attribute;
+    new_attr->av_set_from = OMPI_ATTRIBUTE_FORTRAN_MPI1;
+    return set_value(type, object, keyhash, key, new_attr,
+                     predefined, need_lock);
+}
+
+
+/*
+ * Front-end function called by the Fortran MPI-2 API functions to set
+ * an attribute.
+ */
+int ompi_attr_set_fortran_mpi2(ompi_attribute_type_t type, void *object, 
+                               ompi_hash_table_t **keyhash,
+                               int key, MPI_Aint attribute, 
+                               bool predefined, bool need_lock)
+{
+    attribute_value_t *new_attr = OBJ_NEW(attribute_value_t);
+    if (NULL == new_attr) {
+        return MPI_ERR_SYSRESOURCE;
+    }
+
+    new_attr->av_value = (void *) attribute;
+    new_attr->av_set_from = OMPI_ATTRIBUTE_FORTRAN_MPI2;
+    return set_value(type, object, keyhash, key, new_attr,
+                     predefined, need_lock);
+}
+
+
+/*
+ * Front-end function called by the C MPI API functions to get
+ * attributes.
+ */
+int ompi_attr_get_c(ompi_hash_table_t *keyhash, int key, 
+                    void **attribute, int *flag)
+{
+    attribute_value_t *val;
     int ret;
-    void *attr;
-    ompi_attrkey_item_t *key_item;
 
-    /* According to MPI specs, the call is invalid if key is not
-       present in the main hash at all. If no attribute is associated
-       with the key, then the call is valid and returns FALSE in the
-       flag argument */
-
-    *flag = 0;
-    OMPI_THREAD_LOCK(&alock);
-    ret = ompi_hash_table_get_value_uint32(keyval_hash, key, 
-					   (void**) &key_item);
-
-    if ( OMPI_ERR_NOT_FOUND == ret ) {
-        OMPI_THREAD_UNLOCK(&alock);
-	return MPI_KEYVAL_INVALID;
+    ret = get_value(keyhash, key, &val, flag);
+    if (MPI_SUCCESS == ret && 1 == *flag) {
+        *attribute = translate_to_c(val);
     }
 
-    /* If we have a null keyhash table, that means that nothing has
-       been cached on this object yet.  So just return *flag = 0. */
-
-    if (NULL == keyhash) {
-        OMPI_THREAD_UNLOCK(&alock);
-        return MPI_SUCCESS;
-    }
-
-    ret = ompi_hash_table_get_value_uint32(keyhash, key, &attr);
-    OMPI_THREAD_UNLOCK(&alock);
-    if ( OMPI_SUCCESS == ret ) {
-	*((void **) attribute) = attr;
-	*flag = 1;
-    }
-    return MPI_SUCCESS;
+    return ret;
 }
 
 
-/* There is too much of code copy/paste in here, see if some other
-   logic could work here  */
-int
-ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object, 
-                   void *new_object, ompi_hash_table_t *oldkeyhash,
-                   ompi_hash_table_t *newkeyhash)
+/*
+ * Front-end function called by the Fortran MPI-1 API functions to get
+ * attributes.
+ */
+int ompi_attr_get_fortran_mpi1(ompi_hash_table_t *keyhash, int key, 
+                               MPI_Fint *attribute, int *flag)
+{
+    attribute_value_t *val;
+    int ret;
+
+    ret = get_value(keyhash, key, &val, flag);
+    if (MPI_SUCCESS == ret && 1 == *flag) {
+        *attribute = translate_to_fortran_mpi1(val);
+    }
+
+    return ret;
+}
+
+
+/*
+ * Front-end function called by the Fortran MPI-2 API functions to get
+ * attributes.
+ */
+int ompi_attr_get_fortran_mpi2(ompi_hash_table_t *keyhash, int key, 
+                               MPI_Aint *attribute, int *flag)
+{
+    attribute_value_t *val;
+    int ret;
+
+    ret = get_value(keyhash, key, &val, flag);
+    if (MPI_SUCCESS == ret && 1 == *flag) {
+        *attribute = translate_to_fortran_mpi2(val);
+    }
+
+    return ret;
+}
+
+
+/*
+ * Copy all the attributes from one MPI object to another
+ */
+int ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object, 
+                       void *new_object, ompi_hash_table_t *oldkeyhash,
+                       ompi_hash_table_t *newkeyhash)
 {
     int ret;
     int err;
     uint32_t key;
     int flag;
-    void *node, *in_node, *old_attr, *new_attr;
+    void *node, *in_node;
+    attribute_value_t *old_attr, *new_attr;
     ompi_attrkey_item_t *hash_value;
 
     /* Protect against the user calling ompi_attr_destroy and then
@@ -613,55 +830,70 @@ ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object,
 
     OMPI_THREAD_LOCK(&alock);
 
-    /* Get the first key-attr in the CWD hash */
-    ret = ompi_hash_table_get_first_key_uint32(oldkeyhash, &key, &old_attr,
+    /* Get the first key-attr in the object's key hash */
+    ret = ompi_hash_table_get_first_key_uint32(oldkeyhash, &key, 
+                                               (void **) &old_attr,
                                                &node);
 
-    /* While we still have some key-attr pair in the CWD hash */
+    /* While we still have some key-attr pair in the object's key
+       hash */
     while (OMPI_SUCCESS == ret) {
         in_node = node;
 
-        /* Get the attr_item in the main hash - so that we know what
-           the copy_attr_fn is */
+        /* Get the attr_item in the main keyval hash - so that we know
+           what the copy_attr_fn is */
 
 	err = ompi_hash_table_get_value_uint32(keyval_hash, key, 
 					       (void **) &hash_value);
 
-	/* assert (err == OMPI_SUCCESS); */
-
+        new_attr = OBJ_NEW(attribute_value_t);
         switch (type) {
         case COMM_ATTR:
             /* Now call the copy_attr_fn */
-            COPY_ATTR_OBJECT(communicator, old_object, hash_value, old_attr, new_attr);
+            COPY_ATTR_CALLBACKS(communicator, old_object, hash_value, 
+                                old_attr, new_attr);
             break;
 	    
         case TYPE_ATTR:
             /* Now call the copy_attr_fn */
-            COPY_ATTR_OBJECT(datatype, old_object, hash_value, old_attr, new_attr);
+            COPY_ATTR_CALLBACKS(datatype, old_object, hash_value, 
+                                old_attr, new_attr);
             break;
 
 #if OMPI_WANT_MPI2_ONE_SIDED
         case WIN_ATTR:
             /* Now call the copy_attr_fn */
-            COPY_ATTR_OBJECT(win, old_object, hash_value, old_attr, new_attr);
+            COPY_ATTR_CALLBACKS(win, old_object, hash_value, 
+                                old_attr, new_attr);
             break;
 #endif
         }
 
-        /* Hang this off the new CWD object */
+        /* Hang this off the object's key hash */
 	    
         /* The "predefined" parameter to ompi_attr_set() is set to 1,
            so that no comparison is done for prdefined at all and it
            just falls off the error checking loop in attr_set  */
 
         if (1 == flag) {
-            ompi_attr_set(type, new_object, &newkeyhash, key, 
-                          new_attr, true, false);
+            if (0 != (hash_value->attr_flag & OMPI_KEYVAL_F77)) {
+                if (0 != (hash_value->attr_flag & OMPI_KEYVAL_F77_MPI1)) {
+                    new_attr->av_set_from = OMPI_ATTRIBUTE_FORTRAN_MPI1;
+                } else {
+                    new_attr->av_set_from = OMPI_ATTRIBUTE_FORTRAN_MPI2;
+                }
+            } else {
+                new_attr->av_set_from = OMPI_ATTRIBUTE_C;
+            }
+            set_value(type, new_object, &newkeyhash, key, 
+                      new_attr, true, false);
+        } else {
+            OBJ_RELEASE(new_attr);
         }
 
         ret = ompi_hash_table_get_next_key_uint32(oldkeyhash, &key, 
-                                                  &old_attr, in_node, 
-                                                  &node);
+                                                  (void **) &old_attr, 
+                                                  in_node, &node);
     }
 
     /* All done */
@@ -671,9 +903,11 @@ ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object,
 }
 
 
-int
-ompi_attr_delete_all(ompi_attribute_type_t type, void *object, 
-                     ompi_hash_table_t *keyhash)
+/*
+ * Delete all the attributes on an MPI object
+ */
+int ompi_attr_delete_all(ompi_attribute_type_t type, void *object, 
+                         ompi_hash_table_t *keyhash)
 {
     int key_ret, del_ret;
     uint32_t key, oldkey;
@@ -697,7 +931,7 @@ ompi_attr_delete_all(ompi_attribute_type_t type, void *object,
 
     OMPI_THREAD_LOCK(&alock);
 
-    /* Get the first key in local CWD hash  */
+    /* Get the first key in local object's key hash  */
     key_ret = ompi_hash_table_get_first_key_uint32(keyhash,
                                                &key, &old_attr,
                                                &node);
@@ -725,3 +959,245 @@ ompi_attr_delete_all(ompi_attribute_type_t type, void *object,
     OMPI_THREAD_UNLOCK(&alock);
     return del_ret;
 }
+
+/*************************************************************************/
+
+/*
+ * Back-end function to set an attribute on an MPI object
+ */
+static int set_value(ompi_attribute_type_t type, void *object, 
+                     ompi_hash_table_t **keyhash, int key, 
+                     attribute_value_t *new_attr,
+                     bool predefined, bool need_lock)
+{
+    ompi_attrkey_item_t *key_item;
+    int ret, err;
+    attribute_value_t *old_attr;
+    bool had_old = false;
+
+    /* Protect against the user calling ompi_attr_destroy and then
+       calling any of the functions which use it  */
+    if (NULL == keyval_hash) {
+	return MPI_ERR_INTERN;
+    }
+    if (NULL == keyhash) {
+        return MPI_ERR_INTERN;
+    }
+
+    /* Note that this function can be invoked by ompi_attr_copy_all()
+       to set attributes on the new object (in addition to the
+       top-level MPI_* functions that set attributes).  In these
+       cases, ompi_attr_copy_all() has already locked the keyval_lock,
+       so we should not try to lock it again. */
+
+    if (need_lock) {
+        OMPI_THREAD_LOCK(&alock);
+    }
+    ret = ompi_hash_table_get_value_uint32(keyval_hash, key, 
+					   (void **) &key_item);
+
+    /* If key not found */
+
+    if ((OMPI_SUCCESS != ret ) || (NULL == key_item) || 
+        (key_item->attr_type != type) ||
+	((!predefined) && (key_item->attr_flag & OMPI_KEYVAL_PREDEFINED))) {
+        if (need_lock) {
+            OMPI_THREAD_UNLOCK(&alock);
+        }
+	return OMPI_ERR_BAD_PARAM;
+    }
+
+    /* Do we need to make a new keyhash? */
+
+    if (NULL == *keyhash) {
+        ompi_attr_hash_init(keyhash);
+    }
+
+    /* Now see if the key is present in the object's key hash. If so,
+       delete the old attribute value. */
+
+    ret = ompi_hash_table_get_value_uint32(*keyhash, key, (void**) &old_attr);
+    if (OMPI_SUCCESS == ret)  {
+	switch (type) {
+	case COMM_ATTR:
+	    DELETE_ATTR_CALLBACKS(communicator, old_attr, key_item);
+	    break;
+
+#if OMPI_WANT_MPI2_ONE_SIDED
+	case WIN_ATTR:
+	    DELETE_ATTR_CALLBACKS(win, old_attr, key_item);
+	    break;
+#endif
+
+	case TYPE_ATTR:	    
+	    DELETE_ATTR_CALLBACKS(datatype, old_attr, key_item);
+	    break;
+
+	default:
+            return MPI_ERR_INTERN;
+	}
+	had_old = true;
+        OBJ_RELEASE(old_attr);
+    }
+
+    ret = ompi_hash_table_set_value_uint32(*keyhash, key, new_attr); 
+
+    if (need_lock) {
+        OMPI_THREAD_UNLOCK(&alock);
+    }
+    if (OMPI_SUCCESS != ret) {
+	return ret; 
+    }
+
+    /* Increase the reference count of the object, only if there was no
+       old atribute/no old entry in the object's key hash */
+
+    if (!had_old) {
+	OBJ_RETAIN(key_item);
+    }
+    return MPI_SUCCESS;
+}
+
+
+/*
+ * Back-end function to get an attribute from the hash map and return
+ * it to the caller.  Translation services are not provided -- they're
+ * in small, standalone functions that are called from several
+ * different places.
+ */
+static int get_value(ompi_hash_table_t *keyhash, int key, 
+                     attribute_value_t **attribute, int *flag)
+{
+    int ret;
+    void *attr;
+    ompi_attrkey_item_t *key_item;
+
+    /* According to MPI specs, the call is invalid if key is not
+       present in the main keyval hash at all.  If no attribute is
+       associated with the key, then the call is valid and returns
+       FALSE in the flag argument */
+
+    *flag = 0;
+    OMPI_THREAD_LOCK(&alock);
+    ret = ompi_hash_table_get_value_uint32(keyval_hash, key, 
+					   (void**) &key_item);
+
+    if (OMPI_ERR_NOT_FOUND == ret) {
+        OMPI_THREAD_UNLOCK(&alock);
+	return MPI_KEYVAL_INVALID;
+    }
+
+    /* If we have a null keyhash table, that means that nothing has
+       been cached on this object yet.  So just return *flag = 0. */
+
+    if (NULL == keyhash) {
+        OMPI_THREAD_UNLOCK(&alock);
+        return OMPI_SUCCESS;
+    }
+
+    ret = ompi_hash_table_get_value_uint32(keyhash, key, &attr);
+    OMPI_THREAD_UNLOCK(&alock);
+    if (OMPI_SUCCESS == ret) {
+        *attribute = attr;
+	*flag = 1;
+    }
+    return OMPI_SUCCESS;
+}
+
+
+/*
+ * Take an attribute and translate it according to the cases listed in
+ * the comments at the top of this file.
+ *
+ * This function does not fail -- it is only invoked in "safe"
+ * situations.
+ */
+static void *translate_to_c(attribute_value_t *val)
+{
+    switch (val->av_set_from) {
+    case OMPI_ATTRIBUTE_C:
+        /* Case 1: written in C, read in C (unity) */
+        return val->av_value;
+        break;
+
+    case OMPI_ATTRIBUTE_FORTRAN_MPI1:
+        /* Case 4: written in Fortran MPI-1, read in C */
+        return val->av_integer_pointer;
+        break;
+
+    case OMPI_ATTRIBUTE_FORTRAN_MPI2:
+        /* Case 7: written in Fortran MPI-2, read in C */
+        return val->av_address_kind_pointer;
+        break;
+
+    default:
+        /* Should never reach here */
+        return NULL;
+    }
+}
+
+
+/*
+ * Take an attribute and translate it according to the cases listed in
+ * the comments at the top of this file.
+ *
+ * This function does not fail -- it is only invoked in "safe"
+ * situations.
+ */
+static MPI_Fint translate_to_fortran_mpi1(attribute_value_t *val)
+{
+    switch (val->av_set_from) {
+    case OMPI_ATTRIBUTE_C:
+        /* Case 2: written in C, read in Fortran MPI-1 */
+        return ((MPI_Fint *) &val->av_value)[int_pos];
+        break;
+
+    case OMPI_ATTRIBUTE_FORTRAN_MPI1:
+        /* Case 5: written in Fortran MPI-1, read in Fortran MPI-1
+           (unity) */
+        return *((MPI_Fint *) val->av_integer_pointer);
+        break;
+
+    case OMPI_ATTRIBUTE_FORTRAN_MPI2:
+        /* Case 8: written in Fortran MPI-2, read in Fortran MPI-1 */
+        return *((MPI_Fint *) val->av_integer_pointer);
+        break;
+
+    default:
+        /* Should never reach here */
+        return 0;
+    }
+}
+
+
+/*
+ * Take an attribute and translate it according to the cases listed in
+ * the comments at the top of this file.
+ *
+ * This function does not fail -- it is only invoked in "safe"
+ * situations.
+ */
+static MPI_Aint translate_to_fortran_mpi2(attribute_value_t *val)
+{
+    switch (val->av_set_from) {
+    case OMPI_ATTRIBUTE_C:
+        /* Case 3: written in C, read in Fortran MPI-2 */
+        return (MPI_Aint) val->av_value;
+        break;
+
+    case OMPI_ATTRIBUTE_FORTRAN_MPI1:
+        /* Case 6: written in Fortran MPI-1, read in Fortran MPI-2 */
+        return (MPI_Aint) *((MPI_Fint *) val->av_integer_pointer);
+        break;
+
+    case OMPI_ATTRIBUTE_FORTRAN_MPI2:
+        /* Case 9: written in Fortran MPI-2, read in Fortran MPI-2
+           (unity) */
+        return (MPI_Aint) val->av_value;
+        break;
+
+    default:
+        /* Should never reach here */
+        return 0;
+    }
+}
diff --git a/src/attribute/attribute.h b/src/attribute/attribute.h
index 6424331260..92a5dc967e 100644
--- a/src/attribute/attribute.h
+++ b/src/attribute/attribute.h
@@ -35,16 +35,19 @@
 
 #define ATTR_HASH_SIZE 10
 
-/* Flags for attribute will contain these */
 
-#define OMPI_KEYVAL_PREDEFINED 1
-#define OMPI_KEYVAL_F77 2
-#define OMPI_KEYVAL_F77_OLD 4
+/* 
+ * Flags for keyvals 
+ */
+#define OMPI_KEYVAL_PREDEFINED     0x0001
+#define OMPI_KEYVAL_F77            0x0002
+#define OMPI_KEYVAL_F77_MPI1       0x0004
+
 
 #if defined(c_plusplus) || defined(__cplusplus)
 extern "C" {
 #endif
-enum ompi_attribute_type_t{
+enum ompi_attribute_type_t {
     COMM_ATTR = 1, /**< The attribute belongs to a comm object. Starts
 		      with 1 so that we can have it initialized to 0
 		      using memset in the constructor */
@@ -239,7 +242,8 @@ int ompi_attr_free_keyval(ompi_attribute_type_t type, int *key,
                           bool predefined);
 
 /**
- * Set an attribute on the comm/win/datatype
+ * Set an attribute on the comm/win/datatype in a form valid for C.
+ *
  * @param type           Type of attribute (COMM/WIN/DTYPE) (IN)
  * @param object         The actual Comm/Win/Datatype object (IN)
  * @param keyhash        The attribute hash table hanging on the object(IN/OUT)
@@ -257,14 +261,101 @@ int ompi_attr_free_keyval(ompi_attribute_type_t type, int *key,
  * function is invoked internally (i.e., when we already hold the
  * relevant locks, and we don't want to try to lock them again,
  * recursively).
+ *
+ * All three of these functions (ompi_attr_set_c(),
+ * ompi_attr_set_fortran_mpi1(), and ompi_attr_set_fortran_mpi2())
+ * could have been combined into one function that took some kind of
+ * (void*) and an enum to indicate which way to translate the final
+ * representation, but that just seemed to make an already complicated
+ * situation more complicated through yet another layer of
+ * indirection.  
+ *
+ * So yes, this is more code, but it's clearer and less error-prone
+ * (read: better) this way.
  */
-
-int ompi_attr_set(ompi_attribute_type_t type, void *object, 
-                  ompi_hash_table_t **keyhash,
-                  int key, void *attribute, bool predefined, bool need_lock);
+int ompi_attr_set_c(ompi_attribute_type_t type, void *object, 
+                    ompi_hash_table_t **keyhash,
+                    int key, void *attribute, bool predefined, bool need_lock);
 
 /**
- * Get an attribute on the comm/win/datatype
+ * Set an attribute on the comm/win/datatype in a form valid for
+ * Fortran MPI-1.
+ *
+ * @param type           Type of attribute (COMM/WIN/DTYPE) (IN)
+ * @param object         The actual Comm/Win/Datatype object (IN)
+ * @param keyhash        The attribute hash table hanging on the object(IN/OUT)
+ * @param key            Key val for the attribute (IN)
+ * @param attribute      The actual attribute pointer (IN)
+ * @param predefined     Whether the key is predefined or not 0/1 (IN)
+ * @param need_lock      Whether we need to need to lock the keyval_lock or not
+ * @return OMPI error code
+ *
+ * If (*keyhash) == NULL, a new keyhash will be created and
+ * initialized.
+ *
+ * Note that need_lock should *always* be true when this function is
+ * invoked from an top-level MPI function.  It is only false when this
+ * function is invoked internally (i.e., when we already hold the
+ * relevant locks, and we don't want to try to lock them again,
+ * recursively).
+ *
+ * All three of these functions (ompi_attr_set_c(),
+ * ompi_attr_set_fortran_mpi1(), and ompi_attr_set_fortran_mpi2())
+ * could have been combined into one function that took some kind of
+ * (void*) and an enum to indicate which way to translate the final
+ * representation, but that just seemed to make an already complicated
+ * situation more complicated through yet another layer of
+ * indirection.  
+ *
+ * So yes, this is more code, but it's clearer and less error-prone
+ * (read: better) this way.
+ */
+int ompi_attr_set_fortran_mpi1(ompi_attribute_type_t type, void *object, 
+                               ompi_hash_table_t **keyhash,
+                               int key, MPI_Fint attribute, 
+                               bool predefined, bool need_lock);
+
+/**
+ * Set an attribute on the comm/win/datatype in a form valid for
+ * Fortran MPI-2.
+ *
+ * @param type           Type of attribute (COMM/WIN/DTYPE) (IN)
+ * @param object         The actual Comm/Win/Datatype object (IN)
+ * @param keyhash        The attribute hash table hanging on the object(IN/OUT)
+ * @param key            Key val for the attribute (IN)
+ * @param attribute      The actual attribute pointer (IN)
+ * @param predefined     Whether the key is predefined or not 0/1 (IN)
+ * @param need_lock      Whether we need to need to lock the keyval_lock or not
+ * @return OMPI error code
+ *
+ * If (*keyhash) == NULL, a new keyhash will be created and
+ * initialized.
+ *
+ * Note that need_lock should *always* be true when this function is
+ * invoked from an top-level MPI function.  It is only false when this
+ * function is invoked internally (i.e., when we already hold the
+ * relevant locks, and we don't want to try to lock them again,
+ * recursively).
+ *
+ * All three of these functions (ompi_attr_set_c(),
+ * ompi_attr_set_fortran_mpi1(), and ompi_attr_set_fortran_mpi2())
+ * could have been combined into one function that took some kind of
+ * (void*) and an enum to indicate which way to translate the final
+ * representation, but that just seemed to make an already complicated
+ * situation more complicated through yet another layer of
+ * indirection.  
+ *
+ * So yes, this is more code, but it's clearer and less error-prone
+ * (read: better) this way.
+ */
+int ompi_attr_set_fortran_mpi2(ompi_attribute_type_t type, void *object, 
+                               ompi_hash_table_t **keyhash,
+                               int key, MPI_Aint attribute, 
+                               bool predefined, bool need_lock);
+
+/**
+ * Get an attribute on the comm/win/datatype in a form valid for C.
+ *
  * @param keyhash        The attribute hash table hanging on the object(IN)
  * @param key            Key val for the attribute (IN)
  * @param attribute      The actual attribute pointer (OUT)
@@ -272,10 +363,74 @@ int ompi_attr_set(ompi_attribute_type_t type, void *object,
  *                       with the key (OUT)
  * @return OMPI error code
  *
+ * All three of these functions (ompi_attr_get_c(),
+ * ompi_attr_get_fortran_mpi1(), and ompi_attr_get_fortran_mpi2())
+ * could have been combined into one function that took some kind of
+ * (void*) and an enum to indicate which way to translate the final
+ * representation, but that just seemed to make an already complicated
+ * situation more complicated through yet another layer of
+ * indirection.  
+ *
+ * So yes, this is more code, but it's clearer and less error-prone
+ * (read: better) this way.
  */
 
-int ompi_attr_get(ompi_hash_table_t *keyhash, int key, 
-		 void *attribute, int *flag);
+int ompi_attr_get_c(ompi_hash_table_t *keyhash, int key, 
+                    void **attribute, int *flag);
+
+
+/**
+ * Get an attribute on the comm/win/datatype in a form valid for
+ * Fortran MPI-1.
+ *
+ * @param keyhash        The attribute hash table hanging on the object(IN)
+ * @param key            Key val for the attribute (IN)
+ * @param attribute      The actual attribute pointer (OUT)
+ * @param flag           Flag whether an attribute is associated 
+ *                       with the key (OUT)
+ * @return OMPI error code
+ *
+ * All three of these functions (ompi_attr_get_c(),
+ * ompi_attr_get_fortran_mpi1(), and ompi_attr_get_fortran_mpi2())
+ * could have been combined into one function that took some kind of
+ * (void*) and an enum to indicate which way to translate the final
+ * representation, but that just seemed to make an already complicated
+ * situation more complicated through yet another layer of
+ * indirection.  
+ *
+ * So yes, this is more code, but it's clearer and less error-prone
+ * (read: better) this way.
+ */
+
+int ompi_attr_get_fortran_mpi1(ompi_hash_table_t *keyhash, int key, 
+                               MPI_Fint *attribute, int *flag);
+
+
+/**
+ * Get an attribute on the comm/win/datatype in a form valid for
+ * Fortran MPI-2.
+ *
+ * @param keyhash        The attribute hash table hanging on the object(IN)
+ * @param key            Key val for the attribute (IN)
+ * @param attribute      The actual attribute pointer (OUT)
+ * @param flag           Flag whether an attribute is associated 
+ *                       with the key (OUT)
+ * @return OMPI error code
+ *
+ * All three of these functions (ompi_attr_get_c(),
+ * ompi_attr_get_fortran_mpi1(), and ompi_attr_get_fortran_mpi2())
+ * could have been combined into one function that took some kind of
+ * (void*) and an enum to indicate which way to translate the final
+ * representation, but that just seemed to make an already complicated
+ * situation more complicated through yet another layer of
+ * indirection.  
+ *
+ * So yes, this is more code, but it's clearer and less error-prone
+ * (read: better) this way.
+ */
+
+int ompi_attr_get_fortran_mpi2(ompi_hash_table_t *keyhash, int key, 
+                               MPI_Aint *attribute, int *flag);
 
 
 /**
diff --git a/src/attribute/attribute_predefined.c b/src/attribute/attribute_predefined.c
index 14d60780b8..d3aac7381a 100644
--- a/src/attribute/attribute_predefined.c
+++ b/src/attribute/attribute_predefined.c
@@ -14,6 +14,66 @@
  * $HEADER$
  */
 
+/**
+ * @file
+ *
+ * Setup the predefined attributes in MPI.
+ *
+ * A number of pre-defined attributes are created here, most of which
+ * are exactly what one would expect, but there are a few exceptions
+ * -- so they're documented here.
+ *
+ * Predefined attributes are integer-valued or address-valued (per
+ * MPI-2; see section 4.12.7, keeping in mind that Example 4.13 is
+ * totally wrong -- see src/attribute/attribute.h for a lengthy
+ * explanation of this).  
+ *
+ * The only address-valued attribute is MPI_WIN_BASE.  We treat it as
+ * if it were set from C.  All other attributes are integer-valued.
+ * We treat them as if they were set from Fortran MPI-1 (i.e.,
+ * MPI_ATTR_PUT) or Fortran MPI-2 (i.e., MPI_xxx_ATTR_SET).  Most
+ * attributes are MPI-1 integer-valued, meaning that they are the size
+ * of MPI_Fint (INTEGER).  But MPI_WIN_SIZE and MPI_WIN_DISP_UNIT are
+ * MPI-2 integer-valued, meaning that they are the size of MPI_Aint
+ * (INTEGER(KIND=MPI_ADDRESS_KIND)).
+ *
+ * MPI_TAG_UB is set to a fixed upper limit.
+ *
+ * MPI_HOST is set to MPI_PROC_NULL (per MPI-1, see 7.1.1, p192).
+ *
+ * MPI_IO is set to 1 because OMPI provides IO forwarding.
+ *
+ * MPI_WTIME_IS_GLOBAL is set to 0 (a conservative answer).
+ *
+ * MPI_APPNUM is set as the result of a GPR subscription.
+ *
+ * MPI_LASTUSEDCODE is set to an initial value and is reset every time
+ * MPI_ADD_ERROR_CLASS is invoked.  Its copy function is set to
+ * MPI_COMM_NULL_COPY_FN, meaning that *only* MPI_COMM_WORLD will have
+ * this attribute value.  As such, we only have to update
+ * MPI_COMM_WORLD when this value changes (i.e., since this is an
+ * integer-valued attribute, we have to update this attribute on every
+ * communicator -- using NULL_COPY_FN ensures that only MPI_COMM_WORLD
+ * has this attribute value set).
+ *
+ * MPI_UNIVERSE_SIZE is set as the result of a GPR subscription.
+ *
+ * MPI_WIN_BASE is an address-valued attribute, and is set directly
+ * from MPI_WIN_CREATE.  MPI_WIN_SIZE and MPI_WIN_DISP_UNIT are both
+ * integer-valued attributes, *BUT* at least the MPI_WIN_SIZE is an
+ * MPI_Aint, so in terms of consistency, both should be the same --
+ * hence, we treat them as MPI-2 Fortran integer-valued attributes.
+ * All three of these atrributes have NULL_COPY_FN copy functions; it
+ * doesn't make sense to copy them to new windows (because they're
+ * values specific and unique to each window) -- especially when
+ * WIN_CREATE will explicitly set them on new windows anyway.
+ *
+ * These are not supported yet, but are included here for consistency:
+ *
+ * MPI_IMPI_CLIENT_SIZE, MPI_IMPI_CLIENT_COLOR, MPI_IMPI_HOST_SIZE,
+ * and MPI_IMPI_HOST_COLOR are integer-valued attributes.
+ */
+
 #include "ompi_config.h"
 
 #include "mpi.h"
@@ -23,6 +83,7 @@
 #include "errhandler/errclass.h"
 #include "communicator/communicator.h"
 #include "util/proc_info.h"
+#include "util/sys_info.h"
 #include "mca/ns/ns.h"
 #include "mca/gpr/gpr.h"
 #include "mca/errmgr/errmgr.h"
@@ -32,46 +93,80 @@
 /*
  * Private functions
  */
-static int set(int keyval, void *value);
-
-
-/*
- * Back-end for attribute values
- */
-static int attr_tag_ub = MPI_TAG_UB_VALUE;
-static char *attr_host = NULL;
-static int attr_io = 1;
-static int attr_wtime_is_global = 0;
-
-/* Filled in at run-time, below */
-static int attr_appnum = -1;
-/* Filled in at run-time, below */
-static int attr_universe_size = -1;
-
-#if 0
+static int create_comm(int target_keyval, bool want_inherit);
+#if OMPI_WANT_MPI2_ONE_SIDED
 /* JMS for when we implement windows */
-static int attr_win_base = 0;
-static int attr_win_size = 0;
-static int attr_win_disp_unit = 0;
-#endif
-
-#if 0
-/* JMS for when we implement IMPI */
-static int attr_impi_client_size = 0;
-static int attr_impi_client_color = 0;
-static int attr_impi_host_size = 0;
-static int attr_impi_host_color = 0;
+static int create_win(int target_keyval);
 #endif
+static int set_f(int keyval, MPI_Fint value);
 
 
 int ompi_attr_create_predefined(void)
 {
-    int rc;
+    int rc, ret;
     orte_gpr_trigger_t trig, *trig1;
     orte_gpr_value_t value, *values;
     orte_gpr_subscription_t sub, *sub1;
     orte_jobid_t job;
     
+    /* Create all the keyvals */
+
+    /* DO NOT CHANGE THE ORDER OF CREATING THESE KEYVALS!  This order
+       strictly adheres to the order in mpi.h.  If you change the
+       order here, you must change the order in mpi.h as well! */
+    
+    if (OMPI_SUCCESS != (ret = create_comm(MPI_TAG_UB, true)) ||
+        OMPI_SUCCESS != (ret = create_comm(MPI_HOST, true)) ||
+        OMPI_SUCCESS != (ret = create_comm(MPI_IO, true)) ||
+        OMPI_SUCCESS != (ret = create_comm(MPI_WTIME_IS_GLOBAL, true)) ||
+        OMPI_SUCCESS != (ret = create_comm(MPI_APPNUM, true)) ||
+        OMPI_SUCCESS != (ret = create_comm(MPI_LASTUSEDCODE, false)) ||
+        OMPI_SUCCESS != (ret = create_comm(MPI_UNIVERSE_SIZE, true)) ||
+#if OMPI_WANT_MPI2_ONE_SIDED
+        /* JMS for when we implement windows */
+        OMPI_SUCCESS != (ret = create_win(MPI_WIN_BASE)) ||
+        OMPI_SUCCESS != (ret = create_win(MPI_WIN_SIZE)) ||
+        OMPI_SUCCESS != (ret = create_win(MPI_WIN_DISP_UNIT)) ||
+#endif
+#if 0
+        /* JMS For when we implement IMPI */
+        OMPI_SUCCESS != (ret = create_comm(MPI_IMPI_CLIENT_SIZE, true)) ||
+        OMPI_SUCCESS != (ret = create_comm(MPI_IMPI_CLIENT_COLOR, true)) ||
+        OMPI_SUCCESS != (ret = create_comm(MPI_IMPI_HOST_SIZE, true)) ||
+        OMPI_SUCCESS != (ret = create_comm(MPI_IMPI_HOST_COLOR, true)) ||
+#endif
+        0) {
+        return ret;
+    }
+
+    /* Set default values for everything except UNIVERSE_SIZE and
+       APPNUM. */
+
+    if (OMPI_SUCCESS != (ret = set_f(MPI_TAG_UB, MPI_TAG_UB_VALUE)) ||
+        OMPI_SUCCESS != (ret = set_f(MPI_HOST, MPI_PROC_NULL)) ||
+        OMPI_SUCCESS != (ret = set_f(MPI_IO, 1)) ||
+        OMPI_SUCCESS != (ret = set_f(MPI_WTIME_IS_GLOBAL, 0)) ||
+        OMPI_SUCCESS != (ret = set_f(MPI_LASTUSEDCODE, 
+                                     ompi_errclass_lastused)) ||
+#if 0
+        /* JMS For when we implement IMPI */
+        OMPI_SUCCESS != (ret = set(MPI_IMPI_CLIENT_SIZE,
+                                   &attr_impi_client_size)) ||
+        OMPI_SUCCESS != (ret = set(MPI_IMPI_CLIENT_COLOR, 
+                                   &attr_impi_client_color)) ||
+        OMPI_SUCCESS != (ret = set(MPI_IMPI_HOST_SIZE,
+                                   &attr_impi_host_size)) ||
+        OMPI_SUCCESS != (ret = set(MPI_IMPI_HOST_COLOR, 
+                                   &attr_impi_host_color)) ||
+#endif
+        0) {
+        return ret;
+    }
+
+    /* Now that those are all created, setup the trigger to get the
+       UNIVERSE_SIZE and APPNUM values once everyone has passed
+       stg1. */
+
     if (ORTE_SUCCESS != (rc = orte_ns.get_jobid(&job, orte_process_info.my_name))) {
         ORTE_ERROR_LOG(rc);
         return rc;
@@ -177,11 +272,11 @@ void ompi_attr_create_predefined_callback(
     orte_gpr_notify_data_t *data,
     void *cbdata)
 {
-    int err;
     size_t i, j;
     orte_gpr_keyval_t **keyval;
     orte_gpr_value_t **value;
     orte_jobid_t job;
+    unsigned int universe_size = 0;
 
     /* Set some default values */
 
@@ -189,11 +284,13 @@ void ompi_attr_create_predefined_callback(
         return;
     }
 
-    /* Per conversation between Jeff, Edgar, and Ralph - this needs
-     * to be fixed to properly determine the appnum
+    /* Per conversation between Jeff, Edgar, and Ralph - this needs to
+     * be fixed to properly determine the appnum.  Ignore errors here;
+     * there's no way to propagate the error up, so just try to keep
+     * going.
      */
-    attr_appnum = (int)job;
-    
+    set_f(MPI_APPNUM, (MPI_Fint) job);
+
     /* Query the gpr to find out how many CPUs there will be.
        This will only return a non-empty list in a persistent
        universe.  If we don't have a persistent universe, then just
@@ -215,9 +312,8 @@ void ompi_attr_create_predefined_callback(
      * happens in-between anyway, so this shouldn't cause a problem.
      */
 
-    attr_universe_size = 0;
     if (0 == data->cnt) {  /* no data returned */
-        attr_universe_size = ompi_comm_size(MPI_COMM_WORLD);
+        universe_size = ompi_comm_size(MPI_COMM_WORLD);
     } else {
         value = data->values;
         for (i=0; i < data->cnt; i++) {
@@ -229,54 +325,22 @@ void ompi_attr_create_predefined_callback(
                      */
                     if (ORTE_SIZE == keyval[j]->type) {
                         /* Process slot count */
-                        attr_universe_size += keyval[j]->value.size;
+                        universe_size += keyval[j]->value.size;
                     }
                 }
             }
         }
     }
 
-    /* DO NOT CHANGE THE ORDER OF CREATING THESE KEYVALS!  This order
-       strictly adheres to the order in mpi.h.  If you change the
-       order here, you must change the order in mpi.h as well! */
-
-    if (OMPI_SUCCESS != (err = set(MPI_TAG_UB, &attr_tag_ub)) ||
-        OMPI_SUCCESS != (err = set(MPI_HOST, &attr_host)) ||
-        OMPI_SUCCESS != (err = set(MPI_IO, &attr_io)) ||
-        OMPI_SUCCESS != (err = set(MPI_WTIME_IS_GLOBAL,
-                                   &attr_wtime_is_global)) ||
-        OMPI_SUCCESS != (err = set(MPI_APPNUM, &attr_appnum)) ||
-        OMPI_SUCCESS != (err = set(MPI_LASTUSEDCODE,
-                                   &ompi_errclass_lastused)) ||
-        OMPI_SUCCESS != (err = set(MPI_UNIVERSE_SIZE, &attr_universe_size)) ||
-#if 0
-        /* JMS for when we implement windows */
-        /* JMS BE SURE TO READ ALL OF MPI-2 4.12.7 BEFORE IMPLEMENTING
-           THESE ADDRESS-VALUED ATTRIBUTES! */
-        OMPI_SUCCESS != (err = set(MPI_WIN_BASE, &attr_win_base)) ||
-        OMPI_SUCCESS != (err = set(MPI_WIN_SIZE, &attr_win_size)) ||
-        OMPI_SUCCESS != (err = set(MPI_WIN_DISP_UNIT, &attr_win_disp_unit)) ||
-#endif
-#if 0
-        /* JMS For when we implement IMPI */
-        OMPI_SUCCESS != (err = set(MPI_IMPI_CLIENT_SIZE,
-                                   &attr_impi_client_size)) ||
-        OMPI_SUCCESS != (err = set(MPI_IMPI_CLIENT_COLOR, 
-                                   &attr_impi_client_color)) ||
-        OMPI_SUCCESS != (err = set(MPI_IMPI_HOST_SIZE,
-                                   &attr_impi_host_size)) ||
-        OMPI_SUCCESS != (err = set(MPI_IMPI_HOST_COLOR, 
-                                   &attr_impi_host_color)) ||
-#endif
-        0) {
-        return;
-    }
+    /* Same as above -- ignore errors here because there's nothing we
+       can do if there's any error anyway */
 
+    set_f(MPI_UNIVERSE_SIZE, universe_size);
     return;
 }
 
 
-static int set(int target_keyval, void *value)
+static int create_comm(int target_keyval, bool want_inherit)
 {
     int err;
     int keyval;
@@ -284,18 +348,50 @@ static int set(int target_keyval, void *value)
     ompi_attribute_fn_ptr_union_t del;
 
     keyval = -1;
-    copy.attr_communicator_copy_fn = MPI_COMM_DUP_FN;
+    copy.attr_communicator_copy_fn = 
+        want_inherit ? MPI_COMM_DUP_FN : MPI_COMM_NULL_COPY_FN;
     del.attr_communicator_delete_fn = MPI_COMM_NULL_DELETE_FN;
     err = ompi_attr_create_keyval(COMM_ATTR, copy, del,
                                   &keyval, NULL, OMPI_KEYVAL_PREDEFINED);
-    if (keyval != target_keyval || OMPI_SUCCESS != err) {
+    if (MPI_SUCCESS != err) {
         return err;
     }
-    err = ompi_attr_set(COMM_ATTR, MPI_COMM_WORLD,
-                        &MPI_COMM_WORLD->c_keyhash, keyval, value, true, true);
-    if (OMPI_SUCCESS != err) {
-        return err;
+    if (target_keyval != keyval) {
+        return OMPI_ERR_BAD_PARAM;
     }
-
     return OMPI_SUCCESS;
 }
+
+
+#if OMPI_WANT_MPI2_ONE_SIDED
+/* JMS for when we implement windows */
+static int create_win(int target_keyval)
+{
+    int err;
+    int keyval;
+    ompi_attribute_fn_ptr_union_t copy;
+    ompi_attribute_fn_ptr_union_t del;
+
+    keyval = -1;
+    copy.attr_win_copy_fn = MPI_WIN_NULL_COPY_FN;
+    del.attr_win_delete_fn = MPI_WIN_NULL_DELETE_FN;
+    err = ompi_attr_create_keyval(WIN_ATTR, copy, del,
+                                  &keyval, NULL, OMPI_KEYVAL_PREDEFINED);
+    if (MPI_SUCCESS != err) {
+        return err;
+    }
+    if (target_keyval != keyval) {
+        return OMPI_ERR_BAD_PARAM;
+    }
+    return OMPI_SUCCESS;
+}
+#endif
+
+
+static int set_f(int keyval, MPI_Fint value)
+{
+    return ompi_attr_set_fortran_mpi1(COMM_ATTR, MPI_COMM_WORLD,
+                                      &MPI_COMM_WORLD->c_keyhash, 
+                                      keyval, value, 
+                                      true, true);
+}
diff --git a/src/errhandler/errclass.c b/src/errhandler/errclass.c
index fd358c5f32..d074055b54 100644
--- a/src/errhandler/errclass.c
+++ b/src/errhandler/errclass.c
@@ -402,6 +402,11 @@ int ompi_errclass_add(void)
     newerrclass = OBJ_NEW(ompi_errclass_t);
     newerrclass->cls = ompi_errclass_lastused;
     ompi_errclass_lastused++;
+
+    /* Now need to reset the MPI_LASTUSEDCODE attribute on
+       MPI_COMM_WORLD */
+
+    
     
     ompi_pointer_array_set_item(&ompi_errclasses, newerrclass->cls, newerrclass);
     return OMPI_SUCCESS;
diff --git a/src/mpi/c/attr_get.c b/src/mpi/c/attr_get.c
index 32ebd952f7..92d1244af4 100644
--- a/src/mpi/c/attr_get.c
+++ b/src/mpi/c/attr_get.c
@@ -44,9 +44,11 @@ int MPI_Attr_get(MPI_Comm comm, int keyval, void *attribute_val, int *flag)
 	}
     }
         
-    /* This stuff is very confusing.  Be sure to see MPI-2 4.12.7. */
+    /* This stuff is very confusing.  Be sure to see
+       src/attribute/attribute.c for a lengthy comment explaining Open
+       MPI attribute behavior. */
 
-    ret = ompi_attr_get(comm->c_keyhash, keyval, attribute_val, flag);
+    ret = ompi_attr_get_c(comm->c_keyhash, keyval, attribute_val, flag);
     OMPI_ERRHANDLER_RETURN(ret, comm, ret, FUNC_NAME);
 }
 
diff --git a/src/mpi/c/attr_put.c b/src/mpi/c/attr_put.c
index a16688c025..aa4b3046f5 100644
--- a/src/mpi/c/attr_put.c
+++ b/src/mpi/c/attr_put.c
@@ -44,8 +44,8 @@ int MPI_Attr_put(MPI_Comm comm, int keyval, void *attribute_val)
         }
     }
     
-    ret = ompi_attr_set(COMM_ATTR, comm, &comm->c_keyhash, 
-                        keyval, attribute_val, false, true);
+    ret = ompi_attr_set_c(COMM_ATTR, comm, &comm->c_keyhash, 
+                          keyval, attribute_val, false, true);
     
     OMPI_ERRHANDLER_RETURN(ret, comm, MPI_ERR_OTHER, FUNC_NAME);  
 }
diff --git a/src/mpi/c/comm_get_attr.c b/src/mpi/c/comm_get_attr.c
index b0b3b0448f..004b3df7f7 100644
--- a/src/mpi/c/comm_get_attr.c
+++ b/src/mpi/c/comm_get_attr.c
@@ -44,8 +44,11 @@ int MPI_Comm_get_attr(MPI_Comm comm, int comm_keyval,
 	}
     }
 
-    ret = ompi_attr_get(comm->c_keyhash, comm_keyval, 
-                        attribute_val, flag);
+    /* This stuff is very confusing.  Be sure to see
+       src/attribute/attribute.c for a lengthy comment explaining Open
+       MPI attribute behavior. */
 
+    ret = ompi_attr_get_c(comm->c_keyhash, comm_keyval, 
+                          attribute_val, flag);
     OMPI_ERRHANDLER_RETURN(ret, comm, MPI_ERR_OTHER, FUNC_NAME);  
 }
diff --git a/src/mpi/c/comm_set_attr.c b/src/mpi/c/comm_set_attr.c
index 2fec8616f7..d023641de0 100644
--- a/src/mpi/c/comm_set_attr.c
+++ b/src/mpi/c/comm_set_attr.c
@@ -44,7 +44,7 @@ int MPI_Comm_set_attr(MPI_Comm comm, int comm_keyval, void *attribute_val)
 	}
     }
     
-    ret = ompi_attr_set(COMM_ATTR, comm, &comm->c_keyhash, 
-                        comm_keyval, attribute_val, false, true);
+    ret = ompi_attr_set_c(COMM_ATTR, comm, &comm->c_keyhash, 
+                         comm_keyval, attribute_val, false, true);
     OMPI_ERRHANDLER_RETURN(ret, comm, MPI_ERR_OTHER, FUNC_NAME);  
 }
diff --git a/src/mpi/c/type_get_attr.c b/src/mpi/c/type_get_attr.c
index 3e4a08e66c..ee8e34f907 100644
--- a/src/mpi/c/type_get_attr.c
+++ b/src/mpi/c/type_get_attr.c
@@ -52,8 +52,12 @@ int MPI_Type_get_attr (MPI_Datatype type,
 	}
     }
 
-    ret = ompi_attr_get(type->d_keyhash, type_keyval, 
-                        attribute_val, flag);
+    /* This stuff is very confusing.  Be sure to see
+       src/attribute/attribute.c for a lengthy comment explaining Open
+       MPI attribute behavior. */
+
+    ret = ompi_attr_get_c(type->d_keyhash, type_keyval, 
+                          attribute_val, flag);
     OMPI_ERRHANDLER_RETURN(ret, MPI_COMM_WORLD,
                            MPI_ERR_OTHER, FUNC_NAME);  
 }
diff --git a/src/mpi/c/type_set_attr.c b/src/mpi/c/type_set_attr.c
index 91db7d7b66..7e3bf35c89 100644
--- a/src/mpi/c/type_set_attr.c
+++ b/src/mpi/c/type_set_attr.c
@@ -48,8 +48,8 @@ int MPI_Type_set_attr (MPI_Datatype type,
     }
   }
 
-    ret = ompi_attr_set(TYPE_ATTR, type, &type->d_keyhash, 
-                        type_keyval, attribute_val, false, true);
+    ret = ompi_attr_set_c(TYPE_ATTR, type, &type->d_keyhash, 
+                          type_keyval, attribute_val, false, true);
 
     OMPI_ERRHANDLER_RETURN(ret, MPI_COMM_WORLD,
 			  MPI_ERR_OTHER, FUNC_NAME);  
diff --git a/src/mpi/c/win_get_attr.c b/src/mpi/c/win_get_attr.c
index 6605fe622e..92c25f2942 100644
--- a/src/mpi/c/win_get_attr.c
+++ b/src/mpi/c/win_get_attr.c
@@ -45,7 +45,11 @@ int MPI_Win_get_attr(MPI_Win win, int win_keyval,
 	}
     }
     
-    ret = ompi_attr_get(win->w_keyhash, win_keyval, 
-		       attribute_val, flag);
+    /* This stuff is very confusing.  Be sure to see
+       src/attribute/attribute.c for a lengthy comment explaining Open
+       MPI attribute behavior. */
+
+    ret = ompi_attr_get_c(win->w_keyhash, win_keyval, 
+                          attribute_val, flag);
     OMPI_ERRHANDLER_RETURN(ret, win, MPI_ERR_OTHER, FUNC_NAME);  
 }
diff --git a/src/mpi/f77/attr_get_f.c b/src/mpi/f77/attr_get_f.c
index a85257813a..d0d822d45a 100644
--- a/src/mpi/f77/attr_get_f.c
+++ b/src/mpi/f77/attr_get_f.c
@@ -17,6 +17,8 @@
 #include "ompi_config.h"
 
 #include "mpi/f77/bindings.h"
+#include "attribute/attribute.h"
+#include "communicator/communicator.h"
 
 #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILE_LAYER
 #pragma weak PMPI_ATTR_GET = mpi_attr_get_f
@@ -59,39 +61,15 @@ void mpi_attr_get_f(MPI_Fint *comm, MPI_Fint *keyval,
 		    MPI_Fint *attribute_val, MPI_Fint *flag, MPI_Fint *ierr)
 {
     int c_err, c_flag;
-    MPI_Comm c_comm;
-    ompi_attribute_fortran_ptr_t value;
-
-    c_comm = MPI_Comm_f2c(*comm);
+    MPI_Comm c_comm = MPI_Comm_f2c(*comm);
     
-    /* This stuff is very confusing.  Be sure to see MPI-2 4.12.7. */
+    /* This stuff is very confusing.  Be sure to see the comment at
+       the top of src/attributes/attributes.c. */
 
-    /* Didn't use all the FINT macros that could have prevented a few
-       extra variables in this function, but I figured that the
-       clarity of code, and the fact that this is not expected to be a
-       high-performance function, was worth it */
-
-    /* Note that this function deals with attribute values that are
-       the size of Fortran INTEGERS; the C function MPI_Attr_get deals
-       with attribute values that are the size of address integers.
-       Hence, it is possible that you'll lose some precision upon the
-       cast.  Per MPI-2 4.12.7, use MPI_xxx_GET/SET_ATTR when you need
-       lossless conversion. */
-
-    c_err = MPI_Attr_get(c_comm, OMPI_FINT_2_INT(*keyval), 
-                         &value.c_ptr, &c_flag);
+    c_err = ompi_attr_get_fortran_mpi1(c_comm->c_keyhash, 
+                                       OMPI_FINT_2_INT(*keyval),
+                                       attribute_val, 
+                                       &c_flag);
     *ierr = OMPI_INT_2_FINT(c_err);
     *flag = OMPI_INT_2_FINT(c_flag);
-
-    /* Note that MPI-2 4.12.7 specifically says that Fortran's
-       ATTR_GET function will take the address returned from C and
-       "convert it to an integer".  This compliments ATTR_PUT, who,
-       since we need to save Fortran attributes by value, saves only
-       the MPI_Fint (regardless of the size of the back-end attribute
-       storeage).  So here we simply extract that MPI_Fint and get the
-       value back. */
-
-    if (MPI_SUCCESS == c_err && 1 == c_flag) {
-        *attribute_val = value.f_integer;
-    }
 }
diff --git a/src/mpi/f77/attr_put_f.c b/src/mpi/f77/attr_put_f.c
index d3fdbe1b7d..0f469dbc6c 100644
--- a/src/mpi/f77/attr_put_f.c
+++ b/src/mpi/f77/attr_put_f.c
@@ -17,6 +17,8 @@
 #include "ompi_config.h"
 
 #include "mpi/f77/bindings.h"
+#include "attribute/attribute.h"
+#include "communicator/communicator.h"
 
 #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILE_LAYER
 #pragma weak PMPI_ATTR_PUT = mpi_attr_put_f
@@ -58,32 +60,17 @@ OMPI_GENERATE_F77_BINDINGS (MPI_ATTR_PUT,
 void mpi_attr_put_f(MPI_Fint *comm, MPI_Fint *keyval, MPI_Fint *attribute_val, 
 		    MPI_Fint *ierr)
 {
-    MPI_Comm c_comm;
-    ompi_attribute_fortran_ptr_t convert;
+    int c_err;
+    MPI_Comm c_comm = MPI_Comm_f2c(*comm);
 
-    c_comm = MPI_Comm_f2c(*comm);
+    /* This stuff is very confusing.  Be sure to see the comment at
+       the top of src/attributes/attributes.c. */
 
-    /* This stuff is very confusing.  Be sure to see MPI-2 4.12.7. */
-
-    /* Note that this function deals with attribute values that are
-       the size of Fortran INTEGERS; the C function MPI_Attr_put deals
-       with attribute values that are the size of address integers.
-       Hence, it is possible that the C value is larger than the
-       Fortran value.  MPI says that we sign-extend in this case. */
-
-    /* Fortran attributes are integers.  So we need to save those by
-       value -- not by reference.  Hence, we don't save the pointer to
-       the fortran parameter that came in, but rather its dereferenced
-       value.  Assign to the c_ptr member first, filling out the sign
-       extension. */
-
-    if (OMPI_FINT_2_INT(*attribute_val) >= 0) {
-        convert.c_ptr = (void*) 0;
-    } else {
-        convert.c_ptr = (void*) -1;
-    }
-    convert.f_integer = *attribute_val;
-    *ierr = OMPI_INT_2_FINT(MPI_Attr_put(c_comm, 
-                                         OMPI_FINT_2_INT(*keyval), 
-                                         convert.c_ptr));
+    c_err = ompi_attr_set_fortran_mpi1(COMM_ATTR,
+                                       c_comm,
+                                       &c_comm->c_keyhash,
+                                       OMPI_FINT_2_INT(*keyval), 
+                                       *attribute_val,
+                                       false, true);
+    *ierr = OMPI_INT_2_FINT(c_err);
 }
diff --git a/src/mpi/f77/comm_get_attr_f.c b/src/mpi/f77/comm_get_attr_f.c
index d2f1014140..3efd83349c 100644
--- a/src/mpi/f77/comm_get_attr_f.c
+++ b/src/mpi/f77/comm_get_attr_f.c
@@ -17,6 +17,8 @@
 #include "ompi_config.h"
 
 #include "mpi/f77/bindings.h"
+#include "attribute/attribute.h"
+#include "communicator/communicator.h"
 
 #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILE_LAYER
 #pragma weak PMPI_COMM_GET_ATTR = mpi_comm_get_attr_f
@@ -56,38 +58,19 @@ OMPI_GENERATE_F77_BINDINGS (MPI_COMM_GET_ATTR,
 #endif
 
 void mpi_comm_get_attr_f(MPI_Fint *comm, MPI_Fint *comm_keyval,
-                         MPI_Aint *attribute_val, MPI_Fint *flag, MPI_Fint *ierr)
+                         MPI_Aint *attribute_val, MPI_Fint *flag, 
+                         MPI_Fint *ierr)
 {
     int c_err, c_flag;
-    MPI_Comm c_comm;
-    int *c_value;
+    MPI_Comm c_comm = MPI_Comm_f2c(*comm);
 
-    c_comm = MPI_Comm_f2c(*comm);
+    /* This stuff is very confusing.  Be sure to see the comment at
+       the top of src/attributes/attributes.c. */
 
-    /* This stuff is very confusing.  Be sure to see MPI-2 4.12.7. */
-
-    /* Didn't use all the FINT macros that could have prevented a few
-       extra variables in this function, but I figured that the
-       clarity of code, and the fact that this is not expected to be a
-       high-performance function, was worth it */
-
-    /* Note that there is no conversion on attribute_val -- MPI-2 says
-       that it is supposed to be the right size already */
-
-    c_err = MPI_Comm_get_attr(c_comm, OMPI_FINT_2_INT(*comm_keyval),
-                              &c_value, &c_flag);
+    c_err = ompi_attr_get_fortran_mpi2(c_comm->c_keyhash,
+                                       OMPI_FINT_2_INT(*comm_keyval),
+                                       attribute_val,
+                                       &c_flag);
     *ierr = OMPI_INT_2_FINT(c_err);
     *flag = OMPI_INT_2_FINT(c_flag);
-
-    /* Note that MPI-2 4.12.7 specifically says that Fortran's
-       xxx_GET_ATTR functions will take the address returned from C
-       and "convert it to an integer".  Since we stored the *value* of
-       the attribute in the corresponding xxx_SET_ATTR function, we
-       simply cast here to get the value back (remember, MPI
-       guarantess that xxx_SET_ATTR fortran parameters are the right
-       size). */
-
-    if (MPI_SUCCESS == c_err && 1 == c_flag) {
-        *attribute_val = (MPI_Aint) c_value;
-    }
 }
diff --git a/src/mpi/f77/comm_set_attr_f.c b/src/mpi/f77/comm_set_attr_f.c
index 2c11a64626..1a258d4337 100644
--- a/src/mpi/f77/comm_set_attr_f.c
+++ b/src/mpi/f77/comm_set_attr_f.c
@@ -17,6 +17,8 @@
 #include "ompi_config.h"
 
 #include "mpi/f77/bindings.h"
+#include "attribute/attribute.h"
+#include "communicator/communicator.h"
 
 #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILE_LAYER
 #pragma weak PMPI_COMM_SET_ATTR = mpi_comm_set_attr_f
@@ -58,15 +60,17 @@ OMPI_GENERATE_F77_BINDINGS (MPI_COMM_SET_ATTR,
 void mpi_comm_set_attr_f(MPI_Fint *comm, MPI_Fint *comm_keyval,
 			 MPI_Aint *attribute_val, MPI_Fint *ierr)
 {
+    int c_err;
     MPI_Comm c_comm = MPI_Comm_f2c(*comm);
     
-    /* We save fortran attributes by value, so dereference
-       attribute_val.  MPI-2 guarantees that xxx_SET_ATTR will be
-       called in fortran with an address-sized integer parameter for
-       the attribute, so there's no need to do any size conversions
-       before calling the back-end C function. */
+    /* This stuff is very confusing.  Be sure to see the comment at
+       the top of src/attributes/attributes.c. */
 
-    *ierr = OMPI_INT_2_FINT(MPI_Comm_set_attr(c_comm,
-					      OMPI_FINT_2_INT(*comm_keyval),
-					      (void*) *attribute_val));
+    c_err = ompi_attr_set_fortran_mpi2(COMM_ATTR,
+                                       c_comm,
+                                       &c_comm->c_keyhash,
+                                       OMPI_FINT_2_INT(*comm_keyval), 
+                                       *attribute_val,
+                                       false, true);
+    *ierr = OMPI_INT_2_FINT(c_err);
 }
diff --git a/src/mpi/f77/keyval_create_f.c b/src/mpi/f77/keyval_create_f.c
index d669243d5f..d7f699ce90 100644
--- a/src/mpi/f77/keyval_create_f.c
+++ b/src/mpi/f77/keyval_create_f.c
@@ -77,7 +77,7 @@ void mpi_keyval_create_f(ompi_mpi1_fortran_copy_attr_function* copy_attr_fn,
 
     ret = ompi_attr_create_keyval(COMM_ATTR, copy_fn, del_fn,
                                   keyval, extra_state,
-                                  OMPI_KEYVAL_F77 | OMPI_KEYVAL_F77_OLD);
+                                  OMPI_KEYVAL_F77 | OMPI_KEYVAL_F77_MPI1);
 
     if (MPI_SUCCESS != ret) {
         c_err = OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD,
diff --git a/src/mpi/f77/type_get_attr_f.c b/src/mpi/f77/type_get_attr_f.c
index 00c097c975..b93c0eb5fe 100644
--- a/src/mpi/f77/type_get_attr_f.c
+++ b/src/mpi/f77/type_get_attr_f.c
@@ -17,6 +17,8 @@
 #include "ompi_config.h"
 
 #include "mpi/f77/bindings.h"
+#include "attribute/attribute.h"
+#include "datatype/datatype.h"
 
 #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILE_LAYER
 #pragma weak PMPI_TYPE_GET_ATTR = mpi_type_get_attr_f
@@ -56,38 +58,19 @@ OMPI_GENERATE_F77_BINDINGS (MPI_TYPE_GET_ATTR,
 #endif
 
 void mpi_type_get_attr_f(MPI_Fint *type, MPI_Fint *type_keyval,
-			 MPI_Aint *attribute_val, MPI_Fint *flag, MPI_Fint *ierr)
+			 MPI_Aint *attribute_val, MPI_Fint *flag, 
+                         MPI_Fint *ierr)
 {
     int c_err, c_flag;
-    MPI_Datatype c_type;
-    int *c_value;
+    MPI_Datatype c_type = MPI_Type_f2c(*type);
 
-    c_type = MPI_Type_f2c(*type);
+    /* This stuff is very confusing.  Be sure to see the comment at
+       the top of src/attributes/attributes.c. */
 
-    /* This stuff is very confusing.  Be sure to see MPI-2 4.12.7. */
-
-    /* Didn't use all the FINT macros that could have prevented a few
-       extra variables in this function, but I figured that the
-       clarity of code, and the fact that this is not expected to be a
-       high-performance function, was worth it */
-
-    /* Note that there is no conversion on attribute_val -- MPI-2 says
-       that it is supposed to be the right size already */
-
-    c_err = MPI_Type_get_attr(c_type, OMPI_FINT_2_INT(*type_keyval),
-                              &c_value, &c_flag);
+    c_err = ompi_attr_get_fortran_mpi2(c_type->d_keyhash,
+                                       OMPI_FINT_2_INT(*type_keyval),
+                                       attribute_val,
+                                       &c_flag);
     *ierr = OMPI_INT_2_FINT(c_err);
     *flag = OMPI_INT_2_FINT(c_flag);
-
-    /* Note that MPI-2 4.12.7 specifically says that Fortran's
-       xxx_GET_ATTR functions will take the address returned from C
-       and "convert it to an integer".  Since we stored the *value* of
-       the attribute in the corresponding xxx_SET_ATTR function, we
-       simply cast here to get the value back (remember, MPI
-       guarantess that xxx_SET_ATTR fortran parameters are the right
-       size). */
-
-    if (MPI_SUCCESS == c_err && 1 == c_flag) {
-        *attribute_val = (MPI_Aint) c_value;
-    }
 }
diff --git a/src/mpi/f77/type_set_attr_f.c b/src/mpi/f77/type_set_attr_f.c
index d8844305db..50ce9d195b 100644
--- a/src/mpi/f77/type_set_attr_f.c
+++ b/src/mpi/f77/type_set_attr_f.c
@@ -17,6 +17,8 @@
 #include "ompi_config.h"
 
 #include "mpi/f77/bindings.h"
+#include "attribute/attribute.h"
+#include "datatype/datatype.h"
 
 #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILE_LAYER
 #pragma weak PMPI_TYPE_SET_ATTR = mpi_type_set_attr_f
@@ -55,17 +57,19 @@ OMPI_GENERATE_F77_BINDINGS (MPI_TYPE_SET_ATTR,
 #include "mpi/f77/profile/defines.h"
 #endif
 
-void mpi_type_set_attr_f(MPI_Fint *type, MPI_Fint *type_keyval, MPI_Aint *attr_val, MPI_Fint *ierr)
+void mpi_type_set_attr_f(MPI_Fint *type, MPI_Fint *type_keyval, MPI_Aint *attribute_val, MPI_Fint *ierr)
 {
-    MPI_Datatype c_type = MPI_Type_f2c( *type );
+    int c_err;
+    MPI_Datatype c_type = MPI_Type_f2c(*type);
 
-    /* We save fortran attributes by value, so dereference
-       attribute_val.  MPI-2 guarantees that xxx_SET_ATTR will be
-       called in fortran with an address-sized integer parameter for
-       the attribute, so there's no need to do any size conversions
-       before calling the back-end C function. */
+    /* This stuff is very confusing.  Be sure to see the comment at
+       the top of src/attributes/attributes.c. */
 
-    *ierr = OMPI_INT_2_FINT(MPI_Type_set_attr( c_type, 
-					       OMPI_FINT_2_INT(*type_keyval),
-					       (void*) *attr_val ));
+    c_err = ompi_attr_set_fortran_mpi2(TYPE_ATTR,
+                                       c_type,
+                                       &c_type->d_keyhash,
+                                       OMPI_FINT_2_INT(*type_keyval), 
+                                       *attribute_val,
+                                       false, true);
+    *ierr = OMPI_INT_2_FINT(c_err);
 }
diff --git a/src/mpi/f77/win_get_attr_f.c b/src/mpi/f77/win_get_attr_f.c
index 451033c652..8ab8b32db7 100644
--- a/src/mpi/f77/win_get_attr_f.c
+++ b/src/mpi/f77/win_get_attr_f.c
@@ -17,6 +17,8 @@
 #include "ompi_config.h"
 
 #include "mpi/f77/bindings.h"
+#include "attribute/attribute.h"
+#include "win/win.h"
 
 #if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILE_LAYER
 #pragma weak PMPI_WIN_GET_ATTR = mpi_win_get_attr_f
@@ -59,35 +61,15 @@ void mpi_win_get_attr_f(MPI_Fint *win, MPI_Fint *win_keyval,
 			MPI_Aint *attribute_val, MPI_Fint *flag, MPI_Fint *ierr)
 {
     int c_err, c_flag;
-    MPI_Win c_win;
-    int *c_value;
+    MPI_Win c_win = MPI_Win_f2c(*win);
 
-    c_win = MPI_Win_f2c(*win);
+    /* This stuff is very confusing.  Be sure to see the comment at
+       the top of src/attributes/attributes.c. */
 
-    /* This stuff is very confusing.  Be sure to see MPI-2 4.12.7. */
-
-    /* Didn't use all the FINT macros that could have prevented a few
-       extra variables in this function, but I figured that the
-       clarity of code, and the fact that this is not expected to be a
-       high-performance function, was worth it */
-
-    /* Note that there is no conversion on attribute_val -- MPI-2 says
-       that it is supposed to be the right size already */
-
-    c_err = MPI_Win_get_attr(c_win, OMPI_FINT_2_INT(*win_keyval),
-                              &c_value, &c_flag);
+    c_err = ompi_attr_get_fortran_mpi2(c_win->w_keyhash,
+                                       OMPI_FINT_2_INT(*keyhash),
+                                       attribute_val,
+                                       &c_flag)
     *ierr = OMPI_INT_2_FINT(c_err);
     *flag = OMPI_INT_2_FINT(c_flag);
-
-    /* Note that MPI-2 4.12.7 specifically says that Fortran's
-       xxx_GET_ATTR functions will take the address returned from C
-       and "convert it to an integer"  Since we stored the *value* of
-       the attribute in the corresponding xxx_SET_ATTR function, we
-       simply cast here to get the value back (remember, MPI
-       guarantess that xxx_SET_ATTR fortran parameters are the right
-       size). */
-
-    if (MPI_SUCCESS == c_err && 1 == c_flag) {
-        *attribute_val = (MPI_Aint) c_value;
-    }
 }
diff --git a/src/mpi/f77/win_set_attr_f.c b/src/mpi/f77/win_set_attr_f.c
index f327a30741..38e181e255 100644
--- a/src/mpi/f77/win_set_attr_f.c
+++ b/src/mpi/f77/win_set_attr_f.c
@@ -58,15 +58,17 @@ OMPI_GENERATE_F77_BINDINGS (MPI_WIN_SET_ATTR,
 void mpi_win_set_attr_f(MPI_Fint *win, MPI_Fint *win_keyval,
 			MPI_Aint *attribute_val, MPI_Fint *ierr)
 {
-    MPI_Win c_win = MPI_Win_f2c( *win );
+    int c_err;
+    MPI_Win c_win = MPI_Win_f2c(*win);
 
-    /* We save fortran attributes by value, so dereference
-       attribute_val.  MPI-2 guarantees that xxx_SET_ATTR will be
-       called in fortran with an address-sized integer parameter for
-       the attribute, so there's no need to do any size conversions
-       before calling the back-end C function. */
+    /* This stuff is very confusing.  Be sure to see the comment at
+       the top of src/attributes/attributes.c. */
 
-    *ierr = OMPI_INT_2_FINT(MPI_Win_set_attr( c_win, 
-					      OMPI_FINT_2_INT(*win_keyval),
-					      (void*) *attribute_val ));
+    c_err = ompi_attr_set_fortran_mpi2(WIN_ATTR,
+                                       c_win,
+                                       &c_win->w_keyhash,
+                                       OMPI_FINT_2_INT(*win_keyval), 
+                                       *attribute_val,
+                                       false, true);
+    *ierr = OMPI_INT_2_FINT(c_err);
 }