reupload this
This commit is contained in:
148
initonce.c
Normal file
148
initonce.c
Normal file
@@ -0,0 +1,148 @@
|
||||
#include "progwrp.h"
|
||||
#include "export.h"
|
||||
#include "implementations.h"
|
||||
|
||||
/*
|
||||
The InitOnce structure can be simplified.
|
||||
|
||||
We have 2 bits to play around with (the rest will hold the value of lpContext).
|
||||
|
||||
Bit 0 - indicates initialization is complete
|
||||
Bit 1 - indicates that initialization is asynchronous
|
||||
|
||||
There is also a mutex and a critical section in use. It would be better if they were local to the
|
||||
InitOnce object, but this seems to work very well. As long as the VLC InitOnce-related crashes
|
||||
in Supermium cease, it is good.
|
||||
*/
|
||||
|
||||
#define INIT_COMPLETE 0x1
|
||||
#define INIT_ASYNC 0x2
|
||||
|
||||
BOOL WINAPI Implementation_InitOnceBeginInitialize(
|
||||
LPINIT_ONCE lpInitOnce,
|
||||
DWORD dwFlags,
|
||||
PBOOL fPending,
|
||||
LPVOID *lpContext
|
||||
)
|
||||
/*
|
||||
This function does not have an associated callback function,
|
||||
but it can be used with the INIT_ONCE object to initialize based on the object itself.
|
||||
*/
|
||||
{
|
||||
if(dwFlags & ~(INIT_ONCE_CHECK_ONLY | INIT_ONCE_ASYNC) ||
|
||||
!lpInitOnce || !fPending)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(((ULONG_PTR)lpInitOnce->Ptr & INIT_ASYNC) && !(dwFlags & INIT_ONCE_ASYNC))
|
||||
return FALSE;
|
||||
|
||||
if(dwFlags & INIT_ONCE_ASYNC)
|
||||
InterlockedOr(&lpInitOnce->Ptr, INIT_ASYNC);
|
||||
|
||||
if((ULONG_PTR)lpInitOnce->Ptr & INIT_COMPLETE)
|
||||
{
|
||||
*fPending = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!(dwFlags & INIT_ONCE_CHECK_ONLY))
|
||||
InterlockedOr(&lpInitOnce->Ptr, INIT_COMPLETE);
|
||||
*fPending = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if(lpContext && ((ULONG_PTR)lpInitOnce->Ptr & INIT_COMPLETE))
|
||||
{
|
||||
*lpContext = (ULONG_PTR)lpInitOnce->Ptr - ((ULONG_PTR)lpInitOnce->Ptr % 4);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WINAPI Implementation_InitOnceExecuteOnce(
|
||||
PINIT_ONCE InitOnce,
|
||||
PINIT_ONCE_FN InitFn,
|
||||
PVOID Parameter,
|
||||
LPVOID *Context
|
||||
)
|
||||
{
|
||||
BOOL Result = FALSE;
|
||||
|
||||
if(InitFn && !InitOnce)
|
||||
return InitFn(InitOnce, Parameter, Context);
|
||||
|
||||
if(!InitOnce || !InitFn)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if((ULONG_PTR)InitOnce->Ptr & INIT_COMPLETE)
|
||||
{
|
||||
if(Context)
|
||||
*Context = (ULONG_PTR)InitOnce->Ptr - ((ULONG_PTR)InitOnce->Ptr % 4);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
EnterCriticalSection(&SrwSharedCs);
|
||||
if(((ULONG_PTR)InitOnce->Ptr & INIT_COMPLETE) || Result)
|
||||
goto Result;
|
||||
Result = InitFn(InitOnce, Parameter, Context);
|
||||
|
||||
Result:
|
||||
if(Result)
|
||||
{
|
||||
(ULONG_PTR)InitOnce->Ptr = (ULONG_PTR)Context | ((ULONG_PTR)InitOnce->Ptr & 0x3);
|
||||
InterlockedOr(&InitOnce->Ptr, INIT_COMPLETE);
|
||||
LeaveCriticalSection(&SrwSharedCs);
|
||||
return Result;
|
||||
}
|
||||
else
|
||||
{
|
||||
LeaveCriticalSection(&SrwSharedCs);
|
||||
if ((ULONG_PTR)InitOnce->Ptr & INIT_COMPLETE)
|
||||
return TRUE;
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL WINAPI Implementation_InitOnceComplete(
|
||||
LPINIT_ONCE lpInitOnce,
|
||||
DWORD dwFlags,
|
||||
LPVOID lpContext
|
||||
)
|
||||
{
|
||||
if(!lpInitOnce || dwFlags & ~(INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(dwFlags & INIT_ONCE_INIT_FAILED)
|
||||
{
|
||||
(ULONG_PTR)lpInitOnce->Ptr = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
InterlockedOr(&lpInitOnce->Ptr, INIT_COMPLETE);
|
||||
|
||||
if(lpContext)
|
||||
{
|
||||
InterlockedOr(&lpInitOnce->Ptr, lpContext);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void WINAPI Implementation_InitOnceInitialize(
|
||||
PINIT_ONCE InitOnce
|
||||
)
|
||||
{
|
||||
InitOnce->Ptr = 0;
|
||||
}
|
||||
Reference in New Issue
Block a user