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_QUEUED;
|
||||
SetEvent(globalMgr.jobEvent);
|
||||
}
|
||||
LeaveCriticalSection(&globalMgr.cs);
|
||||
|
||||
|
|
|
@ -130,6 +130,7 @@ static const IBackgroundCopyManagerVtbl BITS_IBackgroundCopyManager_Vtbl =
|
|||
BackgroundCopyManagerImpl globalMgr = {
|
||||
&BITS_IBackgroundCopyManager_Vtbl,
|
||||
{ NULL, -1, 0, 0, 0, 0 },
|
||||
NULL,
|
||||
LIST_INIT(globalMgr.jobs)
|
||||
};
|
||||
|
||||
|
@ -140,3 +141,59 @@ HRESULT BackgroundCopyManagerConstructor(IUnknown *pUnkOuter, LPVOID *ppObj)
|
|||
*ppObj = (IBackgroundCopyManager *) &globalMgr;
|
||||
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
|
||||
{
|
||||
const IBackgroundCopyManagerVtbl *lpVtbl;
|
||||
/* Protects job list and job states */
|
||||
/* Protects job list, job states, and jobEvent */
|
||||
CRITICAL_SECTION cs;
|
||||
HANDLE jobEvent;
|
||||
struct list jobs;
|
||||
} BackgroundCopyManagerImpl;
|
||||
|
||||
|
@ -91,6 +92,7 @@ typedef struct
|
|||
const IClassFactoryVtbl *lpVtbl;
|
||||
} ClassFactoryImpl;
|
||||
|
||||
extern HANDLE stop_event;
|
||||
extern ClassFactoryImpl BITS_ClassFactory;
|
||||
extern BackgroundCopyManagerImpl globalMgr;
|
||||
|
||||
|
@ -104,6 +106,7 @@ HRESULT BackgroundCopyFileConstructor(BackgroundCopyJobImpl *owner,
|
|||
LPVOID *ppObj);
|
||||
HRESULT EnumBackgroundCopyFilesConstructor(LPVOID *ppObj,
|
||||
IBackgroundCopyJob* copyJob);
|
||||
DWORD WINAPI fileTransfer(void *param);
|
||||
|
||||
/* Little helper functions */
|
||||
static inline char *
|
||||
|
|
|
@ -28,10 +28,11 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(qmgr);
|
||||
|
||||
HANDLE stop_event = NULL;
|
||||
|
||||
static WCHAR qmgr_nameW[] = {'B','I','T','S',0};
|
||||
static SERVICE_STATUS_HANDLE status_handle;
|
||||
static SERVICE_STATUS status;
|
||||
static HANDLE stop_event = NULL;
|
||||
|
||||
static VOID
|
||||
UpdateStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
|
||||
|
@ -108,6 +109,8 @@ StartCount(void)
|
|||
VOID WINAPI
|
||||
ServiceMain(DWORD dwArgc, LPWSTR *lpszArgv)
|
||||
{
|
||||
HANDLE fileTxThread;
|
||||
DWORD threadId;
|
||||
TRACE("\n");
|
||||
|
||||
stop_event = CreateEventW(NULL, TRUE, FALSE, NULL);
|
||||
|
@ -129,9 +132,24 @@ ServiceMain(DWORD dwArgc, LPWSTR *lpszArgv)
|
|||
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);
|
||||
|
||||
WaitForSingleObject(stop_event, INFINITE);
|
||||
WaitForSingleObject(fileTxThread, INFINITE);
|
||||
UpdateStatus(SERVICE_STOPPED, NO_ERROR, 0);
|
||||
CloseHandle(stop_event);
|
||||
TRACE("service stoped\n");
|
||||
|
|
Loading…
Reference in New Issue