diff --git a/API.txt b/API.txt
index 467a625..db4e3ae 100644
--- a/API.txt
+++ b/API.txt
@@ -20,3 +20,13 @@ This hook gets called when a lock gets set. Implement this if you want to trigge
 <h4>hook_content_lock_released($nid)</h4>
 This hook is called after a lock has been successfully released from the node identified by $nid.
 Implement this to react to a node losing its lock.
+
+<h4>hook_content_lock_skip_release($node)</h4>
+Implement this hook to prevent a node from being unlocked when it is
+being saved. In the normal case where releasing the lock is allowed,
+the hook should return FALSE. If one such hook returns TRUE, the node
+will remain locked. This might be useful if nodes are being locked and
+programmatic changes involving calls to node_save() should not break
+these locks. This hook cannot stop users or admins from clicking
+`release the lock', it only affects when nodes are unlocked by Saving
+the node.
diff --git a/content_lock.module b/content_lock.module
index 65be26b..7413ae3 100644
--- a/content_lock.module
+++ b/content_lock.module
@@ -116,7 +116,8 @@ function content_lock_nodeapi(&$node, $op, $teaser, $page) {
       }
       break;
     case 'update':
-      if (_content_lock_is_lockable_node($node)) {
+      if (_content_lock_is_lockable_node($node)
+          && _content_lock_is_releasable_node($node)) {
         content_lock_release($node->nid, $user->uid);
       }
       break;
@@ -674,6 +675,18 @@ function _content_lock_is_lockable_node($node) {
   return $lockable[$format][$node->nid];
 }
 
+/**
+ * Check whether or not a node should be released during
+ * hook_nodeapi()'s 'update' phase by querying
+ * hook_content_lock_skip_release().
+ *
+ * @param $node
+ *   The node whose lock is being considered for release.
+ */
+function _content_lock_is_releasable_node($node) {
+  return !count(array_filter(module_invoke_all('content_lock_skip_release', $node)));
+}
+
 function content_lock_views_api() {
   return array(
    'api' => 2.0,
