diff --git a/entity.module b/entity.module
index 81ad379..08c9039 100644
--- a/entity.module
+++ b/entity.module
@@ -529,7 +529,15 @@ function entity_view($entity_type, $entities, $view_mode = 'full', $langcode = N
 }
 
 /**
- * Determines whether the given user has access to an entity.
+ * Determines whether the given user can perform actions on an entity.
+ *
+ * For create operations, the pattern is to create an entity and then
+ * check if the user has create access.
+ *
+ * @code
+ * $node = entity_create('node', array('type' => 'page'));
+ * $access = entity_access('create', 'node', $node, $account);
+ * @endcode
  *
  * @param $op
  *   The operation being performed. One of 'view', 'update', 'create' or
diff --git a/entity.test b/entity.test
index 746713e..b3a1a5d 100644
--- a/entity.test
+++ b/entity.test
@@ -948,6 +948,51 @@ class EntityMetadataTestCase extends EntityWebTestCase {
     $this->assertTrue($wrapper->{$this->field_name}->access('view'), 'Field access granted.');
   }
 
+  public function testNodeCreateAccess() {
+    // Create some users. One with super-powers, one with create perms,
+    // and one with no perms, and a different one to author the node.
+    $admin_account = $this->drupalCreateUser(array(
+      'bypass node access',
+    ));
+    $creator_account = $this->drupalCreateUser(array(
+      'create page content',
+    ));
+    $auth_only_account = $this->drupalCreateUser(array());
+    $node_author_account = $this->drupalCreateUser(array());
+
+    // Make a node object.
+    $settings = array(
+      'uid' => $node_author_account->uid,
+      'type' => 'page',
+      'title' => $this->randomName(32),
+      'body' => array(LANGUAGE_NONE => array(array($this->randomName(64)))),
+    );
+    $node = entity_create('node', $settings);
+
+    // First try the callbacks themselves.
+    $this->assertTrue(entity_metadata_no_hook_node_access('create', $node, $admin_account), 'Create access allowed for ADMIN, for wrapper callback.');
+    $this->assertTrue(entity_metadata_no_hook_node_access('create', $node, $creator_account), 'Create access allowed for CREATOR, for wrapper callback.');
+    $this->assertFalse(entity_metadata_no_hook_node_access('create', $node, $auth_only_account), 'Create access denied for USER, for wrapper callback.');
+
+    // Now try the populated wrapper.
+    $wrapper = entity_metadata_wrapper('node', $node);
+    $this->assertTrue($wrapper->entityAccess('create', $admin_account),
+      'Create access allowed for ADMIN, for populated wrapper.');
+    $this->assertTrue($wrapper->entityAccess('create', $creator_account),
+      'Create access allowed for CREATOR, for populated wrapper.');
+    $this->assertFalse($wrapper->entityAccess('create', $auth_only_account),
+      'Create access denied for USER, for populated wrapper.');
+
+    // Now try the empty wrapper.
+    $wrapper = entity_metadata_wrapper('node', NULL, array('bundle' => 'page'));
+    $this->assertTrue($wrapper->entityAccess('create', $admin_account),
+      'Create access allowed for ADMIN, for empty wrapper.');
+    $this->assertFalse($wrapper->entityAccess('create', $creator_account),
+      'Create access denied for CREATOR, for empty wrapper.');
+    $this->assertFalse($wrapper->entityAccess('create', $auth_only_account),
+      'Create access denied for USER, for empty wrapper.');
+  }
+
   /**
    * Tests using a data structure with passed in metadata.
    */
diff --git a/modules/callbacks.inc b/modules/callbacks.inc
index 304f53f..71adb4a 100644
--- a/modules/callbacks.inc
+++ b/modules/callbacks.inc
@@ -610,11 +610,33 @@ function entity_metadata_field_file_validate_item($items, $context) {
 /**
  * Access callback for the node entity.
  *
- * This function does not implement hook_node_access(), thus it may not be
- * called entity_metadata_node_access().
+ * Why the strange function name? This function does not implement
+ * hook_node_access(), and thus it can't be called
+ * entity_metadata_node_access().
+ *
+ * @see entity_access()
+ *
+ * @param $op
+ *   The operation being performed. One of 'view', 'update', 'create' or
+ *   'delete'.
+ * @param $node
+ *   A node to check access for.
+ * @param $account
+ *   The user to check for. Leave it to NULL to check for the global user.
+ *
+ * @return boolean
+ *   TRUE if access is allowed, FALSE otherwise.
  */
 function entity_metadata_no_hook_node_access($op, $node = NULL, $account = NULL) {
   if (isset($node)) {
+    if ('create' == $op) {
+      // Node's create access system needs a bundle name.
+      if (isset($node->type)) {
+        return node_access($op, $node->type, $account);
+      }
+      // Not possible to derive a bundle name, so access disallowed.
+      return FALSE;
+    }
     // If a non-default revision is given, incorporate revision access.
     $default_revision = node_load($node->nid);
     if ($node->vid != $default_revision->vid) {
@@ -624,11 +646,15 @@ function entity_metadata_no_hook_node_access($op, $node = NULL, $account = NULL)
       return node_access($op, $node, $account);
     }
   }
-  // Is access to all nodes allowed?
-  if (!user_access('access content', $account)) {
-    return FALSE;
+  if ('view' == $op) {
+    if (user_access('access content', $account)) {
+      return TRUE;
+    }
+    if (!isset($account) && node_access_view_all_nodes()) {
+      return TRUE;
+    }
   }
-  if (user_access('bypass node access', $account) || (!isset($account) && $op == 'view' && node_access_view_all_nodes())) {
+  if (user_access('bypass node access', $account)) {
     return TRUE;
   }
   return FALSE;
