qmgr: Add infrastructure for background file transferring.
This commit is contained in:
parent
a7ebdf2eba
commit
374fea0a71
|
@ -139,6 +139,7 @@ static HRESULT WINAPI BITS_IBackgroundCopyJob_Resume(
|
||||||
&& This->state != BG_JOB_STATE_TRANSFERRING)
|
&& This->state != BG_JOB_STATE_TRANSFERRING)
|
||||||
{
|
{
|
||||||
This->state = BG_JOB_STATE_QUEUED;
|
This->state = BG_JOB_STATE_QUEUED;
|
||||||
|
SetEvent(globalMgr.jobEvent);
|
||||||
}
|
}
|
||||||
LeaveCriticalSection(&globalMgr.cs);
|
LeaveCriticalSection(&globalMgr.cs);
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,7 @@ static const IBackgroundCopyManagerVtbl BITS_IBackgroundCopyManager_Vtbl =
|
||||||
BackgroundCopyManagerImpl globalMgr = {
|
BackgroundCopyManagerImpl globalMgr = {
|
||||||
&BITS_IBackgroundCopyManager_Vtbl,
|
&BITS_IBackgroundCopyManager_Vtbl,
|
||||||
{ NULL, -1, 0, 0, 0, 0 },
|
{ NULL, -1, 0, 0, 0, 0 },
|
||||||
|
NULL,
|
||||||
LIST_INIT(globalMgr.jobs)
|
LIST_INIT(globalMgr.jobs)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -140,3 +141,59 @@ HRESULT BackgroundCopyManagerConstructor(IUnknown *pUnkOuter, LPVOID *ppObj)
|
||||||
*ppObj = (IBackgroundCopyManager *) &globalMgr;
|
*ppObj = (IBackgroundCopyManager *) &globalMgr;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DWORD WINAPI fileTransfer(void *param)
|
||||||
|
{
|
||||||
|
BackgroundCopyManagerImpl *qmgr = &globalMgr;
|
||||||
|
HANDLE events[2];
|
||||||
|
|
||||||
|
events[0] = stop_event;
|
||||||
|
events[1] = qmgr->jobEvent;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
BackgroundCopyJobImpl *job, *jobCur;
|
||||||
|
BOOL haveJob = FALSE;
|
||||||
|
|
||||||
|
/* Check if it's the stop_event */
|
||||||
|
if (WaitForMultipleObjects(2, events, FALSE, INFINITE) == WAIT_OBJECT_0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Note that other threads may add files to the job list, but only
|
||||||
|
this thread ever deletes them so we don't need to worry about jobs
|
||||||
|
magically disappearing from the list. */
|
||||||
|
EnterCriticalSection(&qmgr->cs);
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY_SAFE(job, jobCur, &qmgr->jobs, BackgroundCopyJobImpl, entryFromQmgr)
|
||||||
|
{
|
||||||
|
if (job->state == BG_JOB_STATE_ACKNOWLEDGED || job->state == BG_JOB_STATE_CANCELLED)
|
||||||
|
{
|
||||||
|
list_remove(&job->entryFromQmgr);
|
||||||
|
IBackgroundCopyJob_Release((IBackgroundCopyJob *) job);
|
||||||
|
}
|
||||||
|
else if (job->state == BG_JOB_STATE_QUEUED)
|
||||||
|
{
|
||||||
|
haveJob = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (job->state == BG_JOB_STATE_CONNECTING
|
||||||
|
|| job->state == BG_JOB_STATE_TRANSFERRING)
|
||||||
|
{
|
||||||
|
ERR("Invalid state for job %p: %d\n", job, job->state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!haveJob)
|
||||||
|
ResetEvent(qmgr->jobEvent);
|
||||||
|
|
||||||
|
LeaveCriticalSection(&qmgr->cs);
|
||||||
|
|
||||||
|
if (haveJob)
|
||||||
|
{
|
||||||
|
FIXME("Actually process job %p; setting error state\n", job);
|
||||||
|
EnterCriticalSection(&qmgr->cs);
|
||||||
|
job->state = BG_JOB_STATE_ERROR;
|
||||||
|
LeaveCriticalSection(&qmgr->cs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -81,8 +81,9 @@ typedef struct
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
const IBackgroundCopyManagerVtbl *lpVtbl;
|
const IBackgroundCopyManagerVtbl *lpVtbl;
|
||||||
/* Protects job list and job states */
|
/* Protects job list, job states, and jobEvent */
|
||||||
CRITICAL_SECTION cs;
|
CRITICAL_SECTION cs;
|
||||||
|
HANDLE jobEvent;
|
||||||
struct list jobs;
|
struct list jobs;
|
||||||
} BackgroundCopyManagerImpl;
|
} BackgroundCopyManagerImpl;
|
||||||
|
|
||||||
|
@ -91,6 +92,7 @@ typedef struct
|
||||||
const IClassFactoryVtbl *lpVtbl;
|
const IClassFactoryVtbl *lpVtbl;
|
||||||
} ClassFactoryImpl;
|
} ClassFactoryImpl;
|
||||||
|
|
||||||
|
extern HANDLE stop_event;
|
||||||
extern ClassFactoryImpl BITS_ClassFactory;
|
extern ClassFactoryImpl BITS_ClassFactory;
|
||||||
extern BackgroundCopyManagerImpl globalMgr;
|
extern BackgroundCopyManagerImpl globalMgr;
|
||||||
|
|
||||||
|
@ -104,6 +106,7 @@ HRESULT BackgroundCopyFileConstructor(BackgroundCopyJobImpl *owner,
|
||||||
LPVOID *ppObj);
|
LPVOID *ppObj);
|
||||||
HRESULT EnumBackgroundCopyFilesConstructor(LPVOID *ppObj,
|
HRESULT EnumBackgroundCopyFilesConstructor(LPVOID *ppObj,
|
||||||
IBackgroundCopyJob* copyJob);
|
IBackgroundCopyJob* copyJob);
|
||||||
|
DWORD WINAPI fileTransfer(void *param);
|
||||||
|
|
||||||
/* Little helper functions */
|
/* Little helper functions */
|
||||||
static inline char *
|
static inline char *
|
||||||
|
|
|
@ -28,10 +28,11 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(qmgr);
|
WINE_DEFAULT_DEBUG_CHANNEL(qmgr);
|
||||||
|
|
||||||
|
HANDLE stop_event = NULL;
|
||||||
|
|
||||||
static WCHAR qmgr_nameW[] = {'B','I','T','S',0};
|
static WCHAR qmgr_nameW[] = {'B','I','T','S',0};
|
||||||
static SERVICE_STATUS_HANDLE status_handle;
|
static SERVICE_STATUS_HANDLE status_handle;
|
||||||
static SERVICE_STATUS status;
|
static SERVICE_STATUS status;
|
||||||
static HANDLE stop_event = NULL;
|
|
||||||
|
|
||||||
static VOID
|
static VOID
|
||||||
UpdateStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
|
UpdateStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
|
||||||
|
@ -108,6 +109,8 @@ StartCount(void)
|
||||||
VOID WINAPI
|
VOID WINAPI
|
||||||
ServiceMain(DWORD dwArgc, LPWSTR *lpszArgv)
|
ServiceMain(DWORD dwArgc, LPWSTR *lpszArgv)
|
||||||
{
|
{
|
||||||
|
HANDLE fileTxThread;
|
||||||
|
DWORD threadId;
|
||||||
TRACE("\n");
|
TRACE("\n");
|
||||||
|
|
||||||
stop_event = CreateEventW(NULL, TRUE, FALSE, NULL);
|
stop_event = CreateEventW(NULL, TRUE, FALSE, NULL);
|
||||||
|
@ -129,9 +132,24 @@ ServiceMain(DWORD dwArgc, LPWSTR *lpszArgv)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
globalMgr.jobEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
|
||||||
|
if (!globalMgr.jobEvent) {
|
||||||
|
ERR("Couldn't create event: error %d\n", GetLastError());
|
||||||
|
UpdateStatus(SERVICE_STOPPED, NO_ERROR, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fileTxThread = CreateThread(NULL, 0, fileTransfer, NULL, 0, &threadId);
|
||||||
|
if (!fileTxThread)
|
||||||
|
{
|
||||||
|
ERR("Failed starting file transfer thread\n");
|
||||||
|
UpdateStatus(SERVICE_STOPPED, NO_ERROR, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
UpdateStatus(SERVICE_RUNNING, NO_ERROR, 0);
|
UpdateStatus(SERVICE_RUNNING, NO_ERROR, 0);
|
||||||
|
|
||||||
WaitForSingleObject(stop_event, INFINITE);
|
WaitForSingleObject(fileTxThread, INFINITE);
|
||||||
UpdateStatus(SERVICE_STOPPED, NO_ERROR, 0);
|
UpdateStatus(SERVICE_STOPPED, NO_ERROR, 0);
|
||||||
CloseHandle(stop_event);
|
CloseHandle(stop_event);
|
||||||
TRACE("service stoped\n");
|
TRACE("service stoped\n");
|
||||||
|
|
Loading…
Reference in New Issue