ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

file.c
Go to the documentation of this file.
00001 /*
00002  * Queue Manager (BITS) File
00003  *
00004  * Copyright 2007, 2008 Google (Roy Shea, Dan Hipschman)
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #include <stdarg.h>
00022 
00023 #define COBJMACROS
00024 
00025 #include "windef.h"
00026 #include "winbase.h"
00027 #include "winuser.h"
00028 #include "winreg.h"
00029 #include "ole2.h"
00030 #include "urlmon.h"
00031 #include "wininet.h"
00032 
00033 #include "qmgr.h"
00034 #include "wine/debug.h"
00035 
00036 WINE_DEFAULT_DEBUG_CHANNEL(qmgr);
00037 
00038 static void BackgroundCopyFileDestructor(BackgroundCopyFileImpl *This)
00039 {
00040     IBackgroundCopyJob_Release((IBackgroundCopyJob *) This->owner);
00041     HeapFree(GetProcessHeap(), 0, This->info.LocalName);
00042     HeapFree(GetProcessHeap(), 0, This->info.RemoteName);
00043     HeapFree(GetProcessHeap(), 0, This);
00044 }
00045 
00046 static ULONG WINAPI BITS_IBackgroundCopyFile_AddRef(IBackgroundCopyFile* iface)
00047 {
00048     BackgroundCopyFileImpl *This = (BackgroundCopyFileImpl *) iface;
00049     return InterlockedIncrement(&This->ref);
00050 }
00051 
00052 static HRESULT WINAPI BITS_IBackgroundCopyFile_QueryInterface(
00053     IBackgroundCopyFile* iface,
00054     REFIID riid,
00055     void **ppvObject)
00056 {
00057     BackgroundCopyFileImpl *This = (BackgroundCopyFileImpl *) iface;
00058 
00059     if (IsEqualGUID(riid, &IID_IUnknown)
00060         || IsEqualGUID(riid, &IID_IBackgroundCopyFile))
00061     {
00062         *ppvObject = &This->lpVtbl;
00063         BITS_IBackgroundCopyFile_AddRef(iface);
00064         return S_OK;
00065     }
00066 
00067     *ppvObject = NULL;
00068     return E_NOINTERFACE;
00069 }
00070 
00071 
00072 static ULONG WINAPI BITS_IBackgroundCopyFile_Release(
00073     IBackgroundCopyFile* iface)
00074 {
00075     BackgroundCopyFileImpl *This = (BackgroundCopyFileImpl *) iface;
00076     ULONG ref = InterlockedDecrement(&This->ref);
00077 
00078     if (ref == 0)
00079         BackgroundCopyFileDestructor(This);
00080 
00081     return ref;
00082 }
00083 
00084 /* Get the remote name of a background copy file */
00085 static HRESULT WINAPI BITS_IBackgroundCopyFile_GetRemoteName(
00086     IBackgroundCopyFile* iface,
00087     LPWSTR *pVal)
00088 {
00089     BackgroundCopyFileImpl *This = (BackgroundCopyFileImpl *) iface;
00090     int n = (lstrlenW(This->info.RemoteName) + 1) * sizeof(WCHAR);
00091 
00092     *pVal = CoTaskMemAlloc(n);
00093     if (!*pVal)
00094         return E_OUTOFMEMORY;
00095 
00096     memcpy(*pVal, This->info.RemoteName, n);
00097     return S_OK;
00098 }
00099 
00100 static HRESULT WINAPI BITS_IBackgroundCopyFile_GetLocalName(
00101     IBackgroundCopyFile* iface,
00102     LPWSTR *pVal)
00103 {
00104     BackgroundCopyFileImpl *This = (BackgroundCopyFileImpl *) iface;
00105     int n = (lstrlenW(This->info.LocalName) + 1) * sizeof(WCHAR);
00106 
00107     *pVal = CoTaskMemAlloc(n);
00108     if (!*pVal)
00109         return E_OUTOFMEMORY;
00110 
00111     memcpy(*pVal, This->info.LocalName, n);
00112     return S_OK;
00113 }
00114 
00115 static HRESULT WINAPI BITS_IBackgroundCopyFile_GetProgress(
00116     IBackgroundCopyFile* iface,
00117     BG_FILE_PROGRESS *pVal)
00118 {
00119     BackgroundCopyFileImpl *This = (BackgroundCopyFileImpl *) iface;
00120 
00121     EnterCriticalSection(&This->owner->cs);
00122     pVal->BytesTotal = This->fileProgress.BytesTotal;
00123     pVal->BytesTransferred = This->fileProgress.BytesTransferred;
00124     pVal->Completed = This->fileProgress.Completed;
00125     LeaveCriticalSection(&This->owner->cs);
00126 
00127     return S_OK;
00128 }
00129 
00130 static const IBackgroundCopyFileVtbl BITS_IBackgroundCopyFile_Vtbl =
00131 {
00132     BITS_IBackgroundCopyFile_QueryInterface,
00133     BITS_IBackgroundCopyFile_AddRef,
00134     BITS_IBackgroundCopyFile_Release,
00135     BITS_IBackgroundCopyFile_GetRemoteName,
00136     BITS_IBackgroundCopyFile_GetLocalName,
00137     BITS_IBackgroundCopyFile_GetProgress
00138 };
00139 
00140 HRESULT BackgroundCopyFileConstructor(BackgroundCopyJobImpl *owner,
00141                                       LPCWSTR remoteName, LPCWSTR localName,
00142                                       LPVOID *ppObj)
00143 {
00144     BackgroundCopyFileImpl *This;
00145     int n;
00146 
00147     TRACE("(%s,%s,%p)\n", debugstr_w(remoteName),
00148             debugstr_w(localName), ppObj);
00149 
00150     This = HeapAlloc(GetProcessHeap(), 0, sizeof *This);
00151     if (!This)
00152         return E_OUTOFMEMORY;
00153 
00154     n = (lstrlenW(remoteName) + 1) * sizeof(WCHAR);
00155     This->info.RemoteName = HeapAlloc(GetProcessHeap(), 0, n);
00156     if (!This->info.RemoteName)
00157     {
00158         HeapFree(GetProcessHeap(), 0, This);
00159         return E_OUTOFMEMORY;
00160     }
00161     memcpy(This->info.RemoteName, remoteName, n);
00162 
00163     n = (lstrlenW(localName) + 1) * sizeof(WCHAR);
00164     This->info.LocalName = HeapAlloc(GetProcessHeap(), 0, n);
00165     if (!This->info.LocalName)
00166     {
00167         HeapFree(GetProcessHeap(), 0, This->info.RemoteName);
00168         HeapFree(GetProcessHeap(), 0, This);
00169         return E_OUTOFMEMORY;
00170     }
00171     memcpy(This->info.LocalName, localName, n);
00172 
00173     This->lpVtbl = &BITS_IBackgroundCopyFile_Vtbl;
00174     This->ref = 1;
00175 
00176     This->fileProgress.BytesTotal = BG_SIZE_UNKNOWN;
00177     This->fileProgress.BytesTransferred = 0;
00178     This->fileProgress.Completed = FALSE;
00179     This->owner = owner;
00180     IBackgroundCopyJob_AddRef((IBackgroundCopyJob *) owner);
00181 
00182     *ppObj = &This->lpVtbl;
00183     return S_OK;
00184 }
00185 
00186 static DWORD CALLBACK copyProgressCallback(LARGE_INTEGER totalSize,
00187                                            LARGE_INTEGER totalTransferred,
00188                                            LARGE_INTEGER streamSize,
00189                                            LARGE_INTEGER streamTransferred,
00190                                            DWORD streamNum,
00191                                            DWORD reason,
00192                                            HANDLE srcFile,
00193                                            HANDLE dstFile,
00194                                            LPVOID obj)
00195 {
00196     BackgroundCopyFileImpl *file = obj;
00197     BackgroundCopyJobImpl *job = file->owner;
00198     ULONG64 diff;
00199 
00200     EnterCriticalSection(&job->cs);
00201     diff = (file->fileProgress.BytesTotal == BG_SIZE_UNKNOWN
00202             ? totalTransferred.QuadPart
00203             : totalTransferred.QuadPart - file->fileProgress.BytesTransferred);
00204     file->fileProgress.BytesTotal = totalSize.QuadPart;
00205     file->fileProgress.BytesTransferred = totalTransferred.QuadPart;
00206     job->jobProgress.BytesTransferred += diff;
00207     LeaveCriticalSection(&job->cs);
00208 
00209     return (job->state == BG_JOB_STATE_TRANSFERRING
00210             ? PROGRESS_CONTINUE
00211             : PROGRESS_CANCEL);
00212 }
00213 
00214 typedef struct
00215 {
00216     const IBindStatusCallbackVtbl *lpVtbl;
00217     BackgroundCopyFileImpl *file;
00218     LONG ref;
00219 } DLBindStatusCallback;
00220 
00221 static ULONG WINAPI DLBindStatusCallback_AddRef(IBindStatusCallback *iface)
00222 {
00223     DLBindStatusCallback *This = (DLBindStatusCallback *) iface;
00224     return InterlockedIncrement(&This->ref);
00225 }
00226 
00227 static ULONG WINAPI DLBindStatusCallback_Release(IBindStatusCallback *iface)
00228 {
00229     DLBindStatusCallback *This = (DLBindStatusCallback *) iface;
00230     ULONG ref = InterlockedDecrement(&This->ref);
00231 
00232     if (ref == 0)
00233     {
00234         IBackgroundCopyFile_Release((IBackgroundCopyFile *) This->file);
00235         HeapFree(GetProcessHeap(), 0, This);
00236     }
00237 
00238     return ref;
00239 }
00240 
00241 static HRESULT WINAPI DLBindStatusCallback_QueryInterface(
00242     IBindStatusCallback *iface,
00243     REFIID riid,
00244     void **ppvObject)
00245 {
00246     DLBindStatusCallback *This = (DLBindStatusCallback *) iface;
00247 
00248     if (IsEqualGUID(riid, &IID_IUnknown)
00249         || IsEqualGUID(riid, &IID_IBindStatusCallback))
00250     {
00251         *ppvObject = &This->lpVtbl;
00252         DLBindStatusCallback_AddRef(iface);
00253         return S_OK;
00254     }
00255 
00256     *ppvObject = NULL;
00257     return E_NOINTERFACE;
00258 }
00259 
00260 static HRESULT WINAPI DLBindStatusCallback_GetBindInfo(
00261     IBindStatusCallback *iface,
00262     DWORD *grfBINDF,
00263     BINDINFO *pbindinfo)
00264 {
00265     return E_NOTIMPL;
00266 }
00267 
00268 static HRESULT WINAPI DLBindStatusCallback_GetPriority(
00269     IBindStatusCallback *iface,
00270     LONG *pnPriority)
00271 {
00272     return E_NOTIMPL;
00273 }
00274 
00275 static HRESULT WINAPI DLBindStatusCallback_OnDataAvailable(
00276     IBindStatusCallback *iface,
00277     DWORD grfBSCF,
00278     DWORD dwSize,
00279     FORMATETC *pformatetc,
00280     STGMEDIUM *pstgmed)
00281 {
00282     return E_NOTIMPL;
00283 }
00284 
00285 static HRESULT WINAPI DLBindStatusCallback_OnLowResource(
00286     IBindStatusCallback *iface,
00287     DWORD reserved)
00288 {
00289     return E_NOTIMPL;
00290 }
00291 
00292 static HRESULT WINAPI DLBindStatusCallback_OnObjectAvailable(
00293     IBindStatusCallback *iface,
00294     REFIID riid,
00295     IUnknown *punk)
00296 {
00297     return E_NOTIMPL;
00298 }
00299 
00300 static HRESULT WINAPI DLBindStatusCallback_OnProgress(
00301     IBindStatusCallback *iface,
00302     ULONG progress,
00303     ULONG progressMax,
00304     ULONG statusCode,
00305     LPCWSTR statusText)
00306 {
00307     DLBindStatusCallback *This = (DLBindStatusCallback *) iface;
00308     BackgroundCopyFileImpl *file = This->file;
00309     BackgroundCopyJobImpl *job = file->owner;
00310     ULONG64 diff;
00311 
00312     EnterCriticalSection(&job->cs);
00313     diff = (file->fileProgress.BytesTotal == BG_SIZE_UNKNOWN
00314             ? progress
00315             : progress - file->fileProgress.BytesTransferred);
00316     file->fileProgress.BytesTotal = progressMax ? progressMax : BG_SIZE_UNKNOWN;
00317     file->fileProgress.BytesTransferred = progress;
00318     job->jobProgress.BytesTransferred += diff;
00319     LeaveCriticalSection(&job->cs);
00320 
00321     return S_OK;
00322 }
00323 
00324 static HRESULT WINAPI DLBindStatusCallback_OnStartBinding(
00325     IBindStatusCallback *iface,
00326     DWORD dwReserved,
00327     IBinding *pib)
00328 {
00329     return E_NOTIMPL;
00330 }
00331 
00332 static HRESULT WINAPI DLBindStatusCallback_OnStopBinding(
00333     IBindStatusCallback *iface,
00334     HRESULT hresult,
00335     LPCWSTR szError)
00336 {
00337     return E_NOTIMPL;
00338 }
00339 
00340 static const IBindStatusCallbackVtbl DLBindStatusCallback_Vtbl =
00341 {
00342     DLBindStatusCallback_QueryInterface,
00343     DLBindStatusCallback_AddRef,
00344     DLBindStatusCallback_Release,
00345     DLBindStatusCallback_OnStartBinding,
00346     DLBindStatusCallback_GetPriority,
00347     DLBindStatusCallback_OnLowResource,
00348     DLBindStatusCallback_OnProgress,
00349     DLBindStatusCallback_OnStopBinding,
00350     DLBindStatusCallback_GetBindInfo,
00351     DLBindStatusCallback_OnDataAvailable,
00352     DLBindStatusCallback_OnObjectAvailable
00353 };
00354 
00355 static DLBindStatusCallback *DLBindStatusCallbackConstructor(
00356     BackgroundCopyFileImpl *file)
00357 {
00358     DLBindStatusCallback *This = HeapAlloc(GetProcessHeap(), 0, sizeof *This);
00359     if (!This)
00360         return NULL;
00361 
00362     This->lpVtbl = &DLBindStatusCallback_Vtbl;
00363     IBackgroundCopyFile_AddRef((IBackgroundCopyFile *) file);
00364     This->file = file;
00365     This->ref = 1;
00366     return This;
00367 }
00368 
00369 BOOL processFile(BackgroundCopyFileImpl *file, BackgroundCopyJobImpl *job)
00370 {
00371     static const WCHAR prefix[] = {'B','I','T', 0};
00372     IBindStatusCallback *callbackObj;
00373     WCHAR tmpDir[MAX_PATH];
00374     WCHAR tmpName[MAX_PATH];
00375     HRESULT hr;
00376 
00377     if (!GetTempPathW(MAX_PATH, tmpDir))
00378     {
00379         ERR("Couldn't create temp file name: %d\n", GetLastError());
00380         /* Guessing on what state this should give us */
00381         transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSIENT_ERROR);
00382         return FALSE;
00383     }
00384 
00385     if (!GetTempFileNameW(tmpDir, prefix, 0, tmpName))
00386     {
00387         ERR("Couldn't create temp file: %d\n", GetLastError());
00388         /* Guessing on what state this should give us */
00389         transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSIENT_ERROR);
00390         return FALSE;
00391     }
00392 
00393     callbackObj = (IBindStatusCallback *) DLBindStatusCallbackConstructor(file);
00394     if (!callbackObj)
00395     {
00396         ERR("Out of memory\n");
00397         transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSIENT_ERROR);
00398         return FALSE;
00399     }
00400 
00401     EnterCriticalSection(&job->cs);
00402     file->fileProgress.BytesTotal = BG_SIZE_UNKNOWN;
00403     file->fileProgress.BytesTransferred = 0;
00404     file->fileProgress.Completed = FALSE;
00405     LeaveCriticalSection(&job->cs);
00406 
00407     TRACE("Transferring: %s -> %s -> %s\n",
00408           debugstr_w(file->info.RemoteName),
00409           debugstr_w(tmpName),
00410           debugstr_w(file->info.LocalName));
00411 
00412     transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSFERRING);
00413 
00414     DeleteUrlCacheEntryW(file->info.RemoteName);
00415     hr = URLDownloadToFileW(NULL, file->info.RemoteName, tmpName, 0, callbackObj);
00416     IBindStatusCallback_Release(callbackObj);
00417     if (hr == INET_E_DOWNLOAD_FAILURE)
00418     {
00419         TRACE("URLDownload failed, trying local file copy\n");
00420         if (!CopyFileExW(file->info.RemoteName, tmpName, copyProgressCallback,
00421                          file, NULL, 0))
00422         {
00423             ERR("Local file copy failed: error %d\n", GetLastError());
00424             transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_ERROR);
00425             return FALSE;
00426         }
00427     }
00428     else if (FAILED(hr))
00429     {
00430         ERR("URLDownload failed: eh 0x%08x\n", hr);
00431         transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_ERROR);
00432         return FALSE;
00433     }
00434 
00435     if (transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_QUEUED))
00436     {
00437         lstrcpyW(file->tempFileName, tmpName);
00438 
00439         EnterCriticalSection(&job->cs);
00440         file->fileProgress.Completed = TRUE;
00441         job->jobProgress.FilesTransferred++;
00442         LeaveCriticalSection(&job->cs);
00443 
00444         return TRUE;
00445     }
00446     else
00447     {
00448         DeleteFileW(tmpName);
00449         return FALSE;
00450     }
00451 }

Generated on Fri May 25 2012 04:16:00 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.