Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfile.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
1.7.6.1
|