[ros-diffs] [ion] 55801: [KERNEL32]: Rewrite the File Change Notification APIs since they were pretty much wrong (not surprising as we don't implement the functionality in the kernel/filesystems). [KERNEL32]: ...

ion at svn.reactos.org ion at svn.reactos.org
Tue Feb 21 23:27:45 UTC 2012


Author: ion
Date: Tue Feb 21 23:27:45 2012
New Revision: 55801

URL: http://svn.reactos.org/svn/reactos?rev=55801&view=rev
Log:
[KERNEL32]: Rewrite the File Change Notification APIs since they were pretty much wrong (not surprising as we don't implement the functionality in the kernel/filesystems).
[KERNEL32]: Enable support for asynchronous I/O callbacks with SxS/Fusion activation context support. Right now only added to the file Change notification APIs, but ReadFileEx and WriteFileEx should use them too.

Modified:
    trunk/reactos/dll/win32/kernel32/client/file/cnotify.c
    trunk/reactos/dll/win32/kernel32/include/kernel32.h
    trunk/reactos/dll/win32/kernel32/wine/actctx.c

Modified: trunk/reactos/dll/win32/kernel32/client/file/cnotify.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/file/cnotify.c?rev=55801&r1=55800&r2=55801&view=diff
==============================================================================
--- trunk/reactos/dll/win32/kernel32/client/file/cnotify.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/client/file/cnotify.c [iso-8859-1] Tue Feb 21 23:27:45 2012
@@ -9,30 +9,106 @@
  *                  Created 01/11/98
  */
 
-/* INCLUDES *****************************************************************/
+/* INCLUDES *******************************************************************/
 
 #include <k32.h>
 #define NDEBUG
 #include <debug.h>
 
-/* FUNCTIONS ****************************************************************/
-
-/*
- * @implemented
- */
-BOOL WINAPI
-FindCloseChangeNotification (HANDLE hChangeHandle)
-{
-   NTSTATUS Status = NtClose(hChangeHandle);
-   if(!NT_SUCCESS(Status))
-   {
-     BaseSetLastNTError(Status);
-     return FALSE;
-   }
-
-   return TRUE;
-}
-
+/* GLOBALS ********************************************************************/
+
+CHAR staticchangebuff[sizeof(FILE_NOTIFY_INFORMATION) + 16];
+IO_STATUS_BLOCK staticIoStatusBlock;
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+VOID
+WINAPI
+BasepIoCompletion(IN PVOID ApcContext,
+                  IN PIO_STATUS_BLOCK IoStatusBlock,
+                  IN DWORD Reserved)
+{
+    PBASEP_ACTCTX_BLOCK ActivationBlock = ApcContext;
+    LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine;
+    DWORD BytesTransfered, Result;
+    RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActCtx;
+    PVOID ActivationContext = NULL;
+
+    /* Setup the activation frame */
+    RtlZeroMemory(&ActCtx, sizeof(ActCtx));
+    ActCtx.Size = sizeof(ActCtx);
+    ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER;
+
+    /* Check if the routine returned an error */
+    if (NT_ERROR(IoStatusBlock->Status))
+    {
+        /* Convert the error code and don't copy anything */
+        Result = RtlNtStatusToDosError(IoStatusBlock->Status);
+        BytesTransfered = 0;
+    }
+    else
+    {
+        /* Set success code and copy the bytes transferred */
+        Result = ERROR_SUCCESS;
+        BytesTransfered = IoStatusBlock->Information;
+    }
+
+    /* Read context and routine out from the activation block */
+    ActivationContext = ActivationBlock->ActivationContext;
+    CompletionRoutine = ActivationBlock->CompletionRoutine;
+
+    /* Check if the block should be freed */
+    if (!(ActivationBlock->Flags & 1))
+    {
+        /* Free it */
+        BasepFreeActivationContextActivationBlock(ActivationBlock);
+    }
+
+    /* Activate the context, call the routine, and then deactivate the context */
+    RtlActivateActivationContextUnsafeFast(&ActCtx, ActivationContext);
+    CompletionRoutine(Result, BytesTransfered, (LPOVERLAPPED)IoStatusBlock);
+    RtlDeactivateActivationContextUnsafeFast(&ActCtx);
+}
+
+VOID
+WINAPI
+BasepIoCompletionSimple(IN PVOID ApcContext,
+                        IN PIO_STATUS_BLOCK IoStatusBlock,
+                        IN DWORD Reserved)
+{
+    LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine = ApcContext;
+    DWORD Result, BytesTransfered;
+
+    /* Check if the routine returned an error */
+    if (NT_ERROR(IoStatusBlock->Status))
+    {
+        /* Convert the error code and don't copy anything */
+        Result = RtlNtStatusToDosError(IoStatusBlock->Status);
+        BytesTransfered = 0;
+    }
+    else
+    {
+        /* Set success code and copy the bytes transferred */
+        Result = ERROR_SUCCESS;
+        BytesTransfered = IoStatusBlock->Information;
+    }
+
+    /* Call the callback routine */
+    CompletionRoutine(Result, BytesTransfered, (LPOVERLAPPED)IoStatusBlock);
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+FindCloseChangeNotification(IN HANDLE hChangeHandle)
+{
+    /* Just close the handle */
+    return CloseHandle(hChangeHandle);
+}
 
 /*
  * @implemented
@@ -50,206 +126,255 @@
                                           dwNotifyFilter);
 }
 
-
 /*
  * @implemented
  */
 HANDLE
 WINAPI
-FindFirstChangeNotificationW (
-	LPCWSTR	lpPathName,
-	BOOL	bWatchSubtree,
-	DWORD	dwNotifyFilter
-	)
-{
-   NTSTATUS Status;
-   UNICODE_STRING NtPathU;
-   IO_STATUS_BLOCK IoStatus;
-   OBJECT_ATTRIBUTES ObjectAttributes;
-   HANDLE hDir;
-
-   if (!RtlDosPathNameToNtPathName_U (lpPathName,
-                                          &NtPathU,
-                                          NULL,
-                                          NULL))
-   {
-      BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD);
-      return INVALID_HANDLE_VALUE;
-   }
-
-
-
-   InitializeObjectAttributes (&ObjectAttributes,
+FindFirstChangeNotificationW(IN LPCWSTR lpPathName,
+                             IN BOOL bWatchSubtree,
+                             IN DWORD dwNotifyFilter)
+{
+    NTSTATUS Status;
+    UNICODE_STRING NtPathU;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    HANDLE hDir;
+    RTL_RELATIVE_NAME_U RelativeName;
+    PWCHAR PathBuffer;
+    IO_STATUS_BLOCK IoStatusBlock;
+
+    /* Convert to NT path and get the relative name too */
+    if (!RtlDosPathNameToNtPathName_U(lpPathName,
+                                      &NtPathU,
+                                      NULL,
+                                      &RelativeName))
+    {
+        /* Bail out if the path name makes no sense */
+        SetLastError(ERROR_PATH_NOT_FOUND);
+        return INVALID_HANDLE_VALUE;
+    }
+
+    /* Save the path buffer in case we free it later */
+    PathBuffer = NtPathU.Buffer;
+
+    /* If we have a relative name... */
+    if (RelativeName.RelativeName.Length)
+    {
+        /* Do a relative open with only the relative path set */
+        NtPathU = RelativeName.RelativeName;
+    }
+    else
+    {
+        /* Do a full path open with no containing directory */
+        RelativeName.ContainingDirectory = NULL;
+    }
+
+    /* Now open the directory name that was passed in */
+    InitializeObjectAttributes(&ObjectAttributes,
                                &NtPathU,
                                OBJ_CASE_INSENSITIVE,
-                               NULL,
+                               RelativeName.ContainingDirectory,
                                NULL);
-
-   Status = NtOpenFile (&hDir,
-                        SYNCHRONIZE|FILE_LIST_DIRECTORY,
+    Status = NtOpenFile(&hDir,
+                        SYNCHRONIZE | FILE_LIST_DIRECTORY,
                         &ObjectAttributes,
-                        &IoStatus,
-                        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+                        &IoStatusBlock,
+                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                         FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT);
 
-   RtlFreeHeap(RtlGetProcessHeap(),
-               0,
-               NtPathU.Buffer);
-
-
-
-   if (!NT_SUCCESS(Status))
-   {
-      BaseSetLastNTError(Status);
-      return INVALID_HANDLE_VALUE;
-   }
-
-   Status = NtNotifyChangeDirectoryFile(hDir,
-                                        NULL,
-                                        NULL,
-                                        NULL,
-                                        &IoStatus,
-                                        NULL,//Buffer,
-                                        0,//BufferLength,
-                                        dwNotifyFilter,
-                                        (BOOLEAN)bWatchSubtree);
-   if (!NT_SUCCESS(Status))
-   {
-      NtClose(hDir);
-      BaseSetLastNTError(Status);
-      return INVALID_HANDLE_VALUE;
-   }
-
-   return hDir;
-}
-
+    /* Release our buffer and relative name structure */
+    RtlReleaseRelativeName(&RelativeName);
+    RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
+
+    /* Check if the open failed */
+    if (!NT_SUCCESS(Status))
+    {
+        /* Bail out in that case */
+        BaseSetLastNTError(Status);
+        return INVALID_HANDLE_VALUE;
+    }
+
+    /* Now setup the notification on the directory as requested */
+    Status = NtNotifyChangeDirectoryFile(hDir,
+                                         NULL,
+                                         NULL,
+                                         NULL,
+                                         &staticIoStatusBlock,
+                                         staticchangebuff,
+                                         sizeof(staticchangebuff),
+                                         dwNotifyFilter,
+                                         (BOOLEAN)bWatchSubtree);
+    if (!NT_SUCCESS(Status))
+    {
+        /* We failed, close the handle and convert the error */
+        NtClose(hDir);
+        BaseSetLastNTError(Status);
+        hDir = INVALID_HANDLE_VALUE;
+    }
+
+    /* Return the directory handle on success, or invalid handle otherwise */
+    return hDir;
+}
 
 /*
  * @implemented
  */
 BOOL
 WINAPI
-FindNextChangeNotification (
-	HANDLE	hChangeHandle
-	)
-{
-   IO_STATUS_BLOCK IoStatus;
-   NTSTATUS Status;
-
-   Status = NtNotifyChangeDirectoryFile(hChangeHandle,
-      NULL,
-      NULL,
-      NULL,
-      &IoStatus,
-      NULL,//Buffer,
-      0,//BufferLength,
-      FILE_NOTIFY_CHANGE_SECURITY,//meaningless/ignored for subsequent calls, but must contain a valid flag
-      0 //meaningless/ignored for subsequent calls
-      );
-
-   if (!NT_SUCCESS(Status))
-   {
-      BaseSetLastNTError(Status);
-      return FALSE;
-   }
-
-   return TRUE;
-}
-
-
-extern VOID
-(WINAPI ApcRoutine)(PVOID ApcContext,
-      struct _IO_STATUS_BLOCK* IoStatusBlock,
-      ULONG Reserved);
-
+FindNextChangeNotification(IN HANDLE hChangeHandle)
+{
+    NTSTATUS Status;
+
+    /* Just call the native API directly, dealing with the non-optional parameters */
+    Status = NtNotifyChangeDirectoryFile(hChangeHandle,
+                                         NULL,
+                                         NULL,
+                                         NULL,
+                                         &staticIoStatusBlock,
+                                         staticchangebuff,
+                                         sizeof(staticchangebuff),
+                                         FILE_NOTIFY_CHANGE_SECURITY,
+                                         TRUE);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Convert the error code and fail */
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+
+    /* All went well */
+    return TRUE;
+}
 
 /*
  * @implemented
  */
 BOOL
 WINAPI
-ReadDirectoryChangesW(
-    HANDLE hDirectory,
-    LPVOID lpBuffer OPTIONAL,
-    DWORD nBufferLength,
-    BOOL bWatchSubtree,
-    DWORD dwNotifyFilter,
-    LPDWORD lpBytesReturned, /* undefined for asych. operations */
-    LPOVERLAPPED lpOverlapped OPTIONAL,
-    LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine /* OPTIONAL???????? */
-    )
-{
-   PVOID CompletionRoutine;
-   NTSTATUS Status;
-   IO_STATUS_BLOCK IoStatus;
-   HANDLE EventHandle;
-   PIO_APC_ROUTINE IoApcRoutine;
-
-   if (lpOverlapped )
-   {
-      if (lpCompletionRoutine)
-      {
-          CompletionRoutine = (PVOID) lpCompletionRoutine;
-          EventHandle = NULL;
-          IoApcRoutine = ApcRoutine;
-      }
-      else
-      {
-          if (((ULONG_PTR) lpOverlapped->hEvent & 1) == 0)
-              CompletionRoutine = (PVOID) lpOverlapped;
-          else
-              CompletionRoutine = NULL;
-
-          EventHandle = lpOverlapped->hEvent;
-          IoApcRoutine = NULL;
-      }
-
-      lpOverlapped->Internal = STATUS_PENDING;
-   }
-   else
-   {
-       EventHandle = NULL;
-       IoApcRoutine = NULL;
-       CompletionRoutine = NULL;
-   }
-
-   Status = NtNotifyChangeDirectoryFile(
-      hDirectory,
-      EventHandle,
-      IoApcRoutine,
-      CompletionRoutine, /* ApcContext */
-      lpOverlapped ? (PIO_STATUS_BLOCK) lpOverlapped : &IoStatus,
-      lpBuffer,
-      nBufferLength,
-      dwNotifyFilter,
-      (BOOLEAN)bWatchSubtree
-      );
-
-   if ((Status == STATUS_PENDING) && (!lpOverlapped))
-   {
-       Status = NtWaitForSingleObject(hDirectory, FALSE, NULL);
-
-       if (NT_SUCCESS(Status))
-       {
-           Status = IoStatus.Status;
-       }
-   }
-
-   if (!NT_SUCCESS(Status))
-   {
-      BaseSetLastNTError(Status);
-      return FALSE;
-   }
-
-
-   /* NOTE: lpBytesReturned is undefined for asynch. operations */
-   *lpBytesReturned = IoStatus.Information;
-
-   return TRUE;
-}
-
-
-
-
+ReadDirectoryChangesW(IN HANDLE hDirectory,
+                      IN LPVOID lpBuffer OPTIONAL,
+                      IN DWORD nBufferLength,
+                      IN BOOL bWatchSubtree,
+                      IN DWORD dwNotifyFilter,
+                      OUT LPDWORD lpBytesReturned,
+                      IN LPOVERLAPPED lpOverlapped OPTIONAL,
+                      IN LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
+{
+
+    NTSTATUS Status;
+    HANDLE EventHandle;
+    PVOID ApcContext;
+    PIO_APC_ROUTINE ApcRoutine;
+    PBASEP_ACTCTX_BLOCK ActivationContext = NULL;
+    BOOL Result = TRUE;
+    IO_STATUS_BLOCK IoStatusBlock;
+
+    /* Is the caller doing this synchronously? */
+    if (!lpOverlapped)
+    {
+        /* Great, just pass in the parameters */
+        Status = NtNotifyChangeDirectoryFile(hDirectory,
+                                             NULL,
+                                             NULL,
+                                             NULL,
+                                             &IoStatusBlock,
+                                             lpBuffer,
+                                             nBufferLength,
+                                             dwNotifyFilter,
+                                             bWatchSubtree);
+        if (Status == STATUS_PENDING)
+        {
+            /* Wait for completion since we are synchronous */
+            Status = NtWaitForSingleObject(hDirectory, FALSE, NULL);
+            if (!NT_SUCCESS(Status))
+            {
+                /* The wait failed, bail out */
+                BaseSetLastNTError(Status);
+                return FALSE;
+            }
+            
+            /* Retrieve the final status code */
+            Status = IoStatusBlock.Status;
+        }
+
+        /* Did the operation succeed? */
+        if (NT_SUCCESS(Status))
+        {
+            /* Return the bytes transferd and success */
+            *lpBytesReturned = IoStatusBlock.Information;
+            return Result;
+        }
+
+        /* Convert error code and return failure */
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+
+    /* Does the caller want an APC callbac? */
+    if (lpCompletionRoutine)
+    {
+        /* Don't use an event in this case */
+        EventHandle = NULL;
+
+        /* Allocate a Fusion/SxS activation context for the callback routine */
+        Status = BasepAllocateActivationContextActivationBlock(1 | 2,
+                                                               lpCompletionRoutine,
+                                                               lpOverlapped,
+                                                               &ActivationContext);
+        if (!NT_SUCCESS(Status))
+        {
+            /* This failed, so abandon the call */
+            BaseSetLastNTError(Status);
+            return FALSE;
+        }
+
+        /* Use the SxS context as the APC context */
+        ApcContext = ActivationContext;
+        if (ActivationContext)
+        {
+            /* And use a special stub routine that deals with activation */
+            ApcRoutine = BasepIoCompletion;
+        }
+        else
+        {
+            /* If there was no context, however, use the simple stub routine */
+            ApcContext = lpCompletionRoutine;
+            ApcRoutine = BasepIoCompletionSimple;
+        }
+    }
+    else
+    {
+        /* Use the even with no APC routine */
+        EventHandle = lpOverlapped->hEvent;
+        ApcRoutine = 0;
+
+        /* LPOVERLAPPED should be ignored if event is ORed with 1 */
+        ApcContext = (ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped;
+    }
+
+    /* Set the initial status to pending and call the native API */
+    lpOverlapped->Internal = STATUS_PENDING;
+    Status = NtNotifyChangeDirectoryFile(hDirectory,
+                                         EventHandle,
+                                         ApcRoutine,
+                                         ApcContext,
+                                         (PIO_STATUS_BLOCK)lpOverlapped,
+                                         lpBuffer,
+                                         nBufferLength,
+                                         dwNotifyFilter,
+                                         (BOOLEAN)bWatchSubtree);
+    if (NT_ERROR(Status))
+    {
+        /* Normally we cleanup the context in the completon routine, but we failed */
+        if (ActivationContext) BasepFreeActivationContextActivationBlock(ActivationContext);
+
+        /* Convert the error and fail */
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+
+    /* Return success */
+    return Result;
+}
 
 /* EOF */

Modified: trunk/reactos/dll/win32/kernel32/include/kernel32.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/include/kernel32.h?rev=55801&r1=55800&r2=55801&view=diff
==============================================================================
--- trunk/reactos/dll/win32/kernel32/include/kernel32.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/include/kernel32.h [iso-8859-1] Tue Feb 21 23:27:45 2012
@@ -143,6 +143,14 @@
     BaseCurrentDirPlacementMax
 } BASE_CURRENT_DIR_PLACEMENT;
 
+typedef struct _BASEP_ACTCTX_BLOCK
+{
+    ULONG Flags;
+    PVOID ActivationContext;
+    PVOID CompletionContext;
+    LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine;
+} BASEP_ACTCTX_BLOCK, *PBASEP_ACTCTX_BLOCK;
+
 #define BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR    1
 #define BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS  2
 #define BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE 3
@@ -246,6 +254,21 @@
 VOID
 WINAPI
 BaseProcessStartThunk(VOID);
+
+VOID
+NTAPI
+BasepFreeActivationContextActivationBlock(
+    IN PBASEP_ACTCTX_BLOCK ActivationBlock
+);
+
+NTSTATUS
+NTAPI
+BasepAllocateActivationContextActivationBlock(
+    IN DWORD Flags,
+    IN PVOID CompletionRoutine,
+    IN PVOID CompletionContext,
+    OUT PBASEP_ACTCTX_BLOCK *ActivationBlock
+);
 
 __declspec(noreturn)
 VOID

Modified: trunk/reactos/dll/win32/kernel32/wine/actctx.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/wine/actctx.c?rev=55801&r1=55800&r2=55801&view=diff
==============================================================================
--- trunk/reactos/dll/win32/kernel32/wine/actctx.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/wine/actctx.c [iso-8859-1] Tue Feb 21 23:27:45 2012
@@ -280,3 +280,117 @@
     }
     return TRUE;
 }
+
+/* REACTOS PRIVATE ************************************************************/
+
+VOID
+NTAPI
+BasepFreeActivationContextActivationBlock(IN PBASEP_ACTCTX_BLOCK ActivationBlock)
+{
+    /* Exit if there was nothing passed in */
+    if (!ActivationBlock) return;
+    
+    /* Do we have a context? */
+    if (ActivationBlock->ActivationContext)
+    {
+        /* Release and clear it */
+        RtlReleaseActivationContext(ActivationBlock->ActivationContext);
+        ActivationBlock->ActivationContext = NULL;
+    }
+    
+    /* Free the block */
+    RtlFreeHeap(RtlGetProcessHeap(), 0, ActivationBlock);
+}
+
+NTSTATUS
+NTAPI
+BasepAllocateActivationContextActivationBlock(IN DWORD Flags,
+                                              IN PVOID CompletionRoutine,
+                                              IN PVOID CompletionContext,
+                                              OUT PBASEP_ACTCTX_BLOCK *ActivationBlock)
+{
+    NTSTATUS Status;
+    ACTIVATION_CONTEXT_BASIC_INFORMATION ContextInfo;
+
+    /* Clear the info structure */
+    ContextInfo.dwFlags = 0;
+    ContextInfo.hActCtx = NULL;
+
+    /* Assume failure */
+    if (ActivationBlock) *ActivationBlock = NULL;
+
+    /* Only support valid flags */
+    if (Flags & ~(1 | 2)) // FIXME: What are they? 2 looks like BASEP_ACTCTX_FORCE_BLOCK
+    {
+        /* Fail if unknown flags are passed in */
+        Status = STATUS_INVALID_PARAMETER_1;
+        goto Quickie;
+    }
+
+    /* Caller should have passed in an activation block */
+    if (!ActivationBlock)
+    {
+        /* Fail otherwise */
+        Status = STATUS_INVALID_PARAMETER_4;
+        goto Quickie;
+    }
+
+    /* Query RTL for information on the current activation context */
+    Status = RtlQueryInformationActivationContext(1,
+                                                  NULL,
+                                                  0,
+                                                  ActivationContextBasicInformation,
+                                                  &ContextInfo,
+                                                  sizeof(ContextInfo),
+                                                  NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Failed -- bail out */
+        DPRINT1("SXS: %s - Failure getting active activation context; ntstatus %08lx\n",
+                __FUNCTION__, Status);
+        goto Quickie;
+    }
+
+    /* Check if the current one should be freed */
+    if (ContextInfo.dwFlags & 1)
+    {
+        /* Release and clear it */
+        RtlReleaseActivationContext(ContextInfo.hActCtx);
+        ContextInfo.hActCtx = NULL;
+    }
+
+    /* Check if there's an active context, or if the caller is forcing one */
+    if (!(Flags & 2) || (ContextInfo.hActCtx))
+    {
+        /* Allocate the block */
+        *ActivationBlock = RtlAllocateHeap(RtlGetProcessHeap(),
+                                           0,
+                                           sizeof(BASEP_ACTCTX_BLOCK));
+        if (!(*ActivationBlock))
+        {
+            /* Ran out of memory, fail */
+            Status = STATUS_NO_MEMORY;
+            goto Quickie;
+        }
+
+        /* Fill it out */
+        (*ActivationBlock)->ActivationContext = ContextInfo.hActCtx;
+        (*ActivationBlock)->Flags = 0;
+        if (Flags & 1) (*ActivationBlock)->Flags |= 1; // Not sure about this flag
+        (*ActivationBlock)->CompletionRoutine = CompletionRoutine;
+        (*ActivationBlock)->CompletionContext = CompletionContext;
+
+        /* Tell Quickie below not to free anything, since this is success */
+        ContextInfo.hActCtx = NULL;
+    }
+
+    /* Set success status */
+    Status = STATUS_SUCCESS;
+
+Quickie:
+    /* Failure or success path, return to caller and free on failure */
+    if (ContextInfo.hActCtx) RtlReleaseActivationContext(ContextInfo.hActCtx);
+    return Status;
+}
+
+/* EOF */




More information about the Ros-diffs mailing list