Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenthread.c
Go to the documentation of this file.
00001 /* 00002 * SHLWAPI thread and MT synchronisation functions 00003 * 00004 * Copyright 2002 Juergen Schmied 00005 * Copyright 2002 Jon Griffiths 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 #include <stdarg.h> 00022 #include <string.h> 00023 00024 #define COBJMACROS 00025 00026 #include "windef.h" 00027 #include "winbase.h" 00028 #include "winnls.h" 00029 #include "winuser.h" 00030 #define NO_SHLWAPI_REG 00031 #define NO_SHLWAPI_PATH 00032 #define NO_SHLWAPI_GDI 00033 #define NO_SHLWAPI_STREAM 00034 #define NO_SHLWAPI_USER 00035 #include "shlwapi.h" 00036 #include "shlobj.h" 00037 #include "wine/debug.h" 00038 00039 WINE_DEFAULT_DEBUG_CHANNEL(shell); 00040 00041 extern DWORD SHLWAPI_ThreadRef_index; /* Initialised in shlwapi_main.c */ 00042 00043 INT WINAPI SHStringFromGUIDA(REFGUID,LPSTR,INT); 00044 00045 /************************************************************************** 00046 * CreateAllAccessSecurityAttributes [SHLWAPI.356] 00047 * 00048 * Initialise security attributes from a security descriptor. 00049 * 00050 * PARAMS 00051 * lpAttr [O] Security attributes 00052 * lpSec [I] Security descriptor 00053 * 00054 * RETURNS 00055 * Success: lpAttr, initialised using lpSec. 00056 * Failure: NULL, if any parameters are invalid. 00057 * 00058 * NOTES 00059 * This function always returns NULL if the underlying OS version 00060 * Wine is impersonating does not use security descriptors (i.e. anything 00061 * before Windows NT). 00062 */ 00063 LPSECURITY_ATTRIBUTES WINAPI CreateAllAccessSecurityAttributes( 00064 LPSECURITY_ATTRIBUTES lpAttr, 00065 PSECURITY_DESCRIPTOR lpSec, 00066 DWORD p3) 00067 { 00068 /* This function is used within SHLWAPI only to create security attributes 00069 * for shell semaphores. */ 00070 00071 TRACE("(%p,%p,%08x)\n", lpAttr, lpSec, p3); 00072 00073 if (!(GetVersion() & 0x80000000)) /* NT */ 00074 { 00075 if (!lpSec || !lpAttr) 00076 return NULL; 00077 00078 if (InitializeSecurityDescriptor(lpSec, 1)) 00079 { 00080 if (SetSecurityDescriptorDacl(lpSec, TRUE, NULL, FALSE)) 00081 { 00082 lpAttr->nLength = sizeof(SECURITY_ATTRIBUTES); 00083 lpAttr->lpSecurityDescriptor = lpSec; 00084 lpAttr->bInheritHandle = FALSE; 00085 return lpAttr; 00086 } 00087 } 00088 } 00089 return NULL; 00090 } 00091 00092 /************************************************************************* 00093 * _SHGetInstanceExplorer [SHLWAPI.@] 00094 * 00095 * Get an interface to the shell explorer. 00096 * 00097 * PARAMS 00098 * lppUnknown [O] Destination for explorers IUnknown interface. 00099 * 00100 * RETURNS 00101 * Success: S_OK. lppUnknown contains the explorer interface. 00102 * Failure: An HRESULT error code. 00103 */ 00104 HRESULT WINAPI _SHGetInstanceExplorer(IUnknown **lppUnknown) 00105 { 00106 /* This function is used within SHLWAPI only to hold the IE reference 00107 * for threads created with the CTF_PROCESS_REF flag set. */ 00108 return SHGetInstanceExplorer(lppUnknown); 00109 } 00110 00111 /* Internal thread information structure */ 00112 typedef struct tagSHLWAPI_THREAD_INFO 00113 { 00114 LPTHREAD_START_ROUTINE pfnThreadProc; /* Thread start */ 00115 LPTHREAD_START_ROUTINE pfnCallback; /* Thread initialisation */ 00116 PVOID pData; /* Application specific data */ 00117 BOOL bInitCom; /* Initialise COM for the thread? */ 00118 HANDLE hEvent; /* Signal for creator to continue */ 00119 IUnknown *refThread; /* Reference to thread creator */ 00120 IUnknown *refIE; /* Reference to the IE process */ 00121 } SHLWAPI_THREAD_INFO, *LPSHLWAPI_THREAD_INFO; 00122 00123 typedef struct 00124 { 00125 const IUnknownVtbl* lpVtbl; 00126 LONG *ref; 00127 } threadref; 00128 00129 static HRESULT WINAPI threadref_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppvObj) 00130 { 00131 threadref * This = (threadref *)iface; 00132 00133 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppvObj); 00134 00135 if (ppvObj == NULL) 00136 return E_POINTER; 00137 00138 if (IsEqualGUID(&IID_IUnknown, riid)) { 00139 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppvObj); 00140 *ppvObj = This; 00141 IUnknown_AddRef((IUnknown*)*ppvObj); 00142 return S_OK; 00143 } 00144 00145 *ppvObj = NULL; 00146 FIXME("(%p, %s, %p) interface not supported\n", This, debugstr_guid(riid), ppvObj); 00147 return E_NOINTERFACE; 00148 } 00149 00150 static ULONG WINAPI threadref_AddRef(IUnknown *iface) 00151 { 00152 threadref * This = (threadref *)iface; 00153 00154 TRACE("(%p)\n", This); 00155 return InterlockedIncrement(This->ref); 00156 } 00157 00158 static ULONG WINAPI threadref_Release(IUnknown *iface) 00159 { 00160 LONG refcount; 00161 threadref * This = (threadref *)iface; 00162 00163 TRACE("(%p)\n", This); 00164 00165 refcount = InterlockedDecrement(This->ref); 00166 if (!refcount) 00167 HeapFree(GetProcessHeap(), 0, This); 00168 00169 return refcount; 00170 } 00171 00172 /* VTable */ 00173 static const IUnknownVtbl threadref_vt = 00174 { 00175 threadref_QueryInterface, 00176 threadref_AddRef, 00177 threadref_Release, 00178 }; 00179 00180 /************************************************************************* 00181 * SHCreateThreadRef [SHLWAPI.@] 00182 * 00183 * Create a per-thread IUnknown object 00184 * 00185 * PARAMS 00186 * lprefcount [I] Pointer to a LONG to be used as refcount 00187 * lppUnknown [O] Destination to receive the created object reference 00188 * 00189 * RETURNS 00190 * Success: S_OK. lppUnknown is set to the object reference. 00191 * Failure: E_INVALIDARG, if a parameter is NULL 00192 */ 00193 HRESULT WINAPI SHCreateThreadRef(LONG *lprefcount, IUnknown **lppUnknown) 00194 { 00195 threadref * This; 00196 TRACE("(%p, %p)\n", lprefcount, lppUnknown); 00197 00198 if (!lprefcount || !lppUnknown) 00199 return E_INVALIDARG; 00200 00201 This = HeapAlloc(GetProcessHeap(), 0, sizeof(threadref)); 00202 This->lpVtbl = &threadref_vt; 00203 This->ref = lprefcount; 00204 00205 *lprefcount = 1; 00206 *lppUnknown = (IUnknown *) This; 00207 TRACE("=> returning S_OK with %p\n", This); 00208 return S_OK; 00209 } 00210 00211 /************************************************************************* 00212 * SHGetThreadRef [SHLWAPI.@] 00213 * 00214 * Get a per-thread object reference set by SHSetThreadRef(). 00215 * 00216 * PARAMS 00217 * lppUnknown [O] Destination to receive object reference 00218 * 00219 * RETURNS 00220 * Success: S_OK. lppUnknown is set to the object reference. 00221 * Failure: E_NOINTERFACE, if an error occurs or no object is set 00222 */ 00223 HRESULT WINAPI SHGetThreadRef(IUnknown **lppUnknown) 00224 { 00225 TRACE("(%p)\n", lppUnknown); 00226 00227 if (SHLWAPI_ThreadRef_index == TLS_OUT_OF_INDEXES) 00228 return E_NOINTERFACE; 00229 00230 *lppUnknown = TlsGetValue(SHLWAPI_ThreadRef_index); 00231 if (!*lppUnknown) 00232 return E_NOINTERFACE; 00233 00234 /* Add a reference. Caller will Release() us when finished */ 00235 IUnknown_AddRef(*lppUnknown); 00236 return S_OK; 00237 } 00238 00239 /************************************************************************* 00240 * SHSetThreadRef [SHLWAPI.@] 00241 * 00242 * Store a per-thread object reference. 00243 * 00244 * PARAMS 00245 * lpUnknown [I] Object reference to store 00246 * 00247 * RETURNS 00248 * Success: S_OK. lpUnknown is stored and can be retrieved by SHGetThreadRef() 00249 * Failure: E_NOINTERFACE, if an error occurs 00250 */ 00251 HRESULT WINAPI SHSetThreadRef(IUnknown *lpUnknown) 00252 { 00253 TRACE("(%p)\n", lpUnknown); 00254 00255 if (SHLWAPI_ThreadRef_index == TLS_OUT_OF_INDEXES) 00256 return E_NOINTERFACE; 00257 00258 TlsSetValue(SHLWAPI_ThreadRef_index, lpUnknown); 00259 return S_OK; 00260 } 00261 00262 /************************************************************************* 00263 * SHReleaseThreadRef [SHLWAPI.@] 00264 * 00265 * Release a per-thread object reference. 00266 * 00267 * PARAMS 00268 * None. 00269 * 00270 * RETURNS 00271 * Success: S_OK. The threads object reference is released. 00272 * Failure: An HRESULT error code. 00273 */ 00274 HRESULT WINAPI SHReleaseThreadRef(void) 00275 { 00276 FIXME("() - stub!\n"); 00277 return S_OK; 00278 } 00279 00280 /************************************************************************* 00281 * SHLWAPI_ThreadWrapper 00282 * 00283 * Internal wrapper for executing user thread functions from SHCreateThread. 00284 */ 00285 static DWORD WINAPI SHLWAPI_ThreadWrapper(PVOID pTi) 00286 { 00287 SHLWAPI_THREAD_INFO ti; 00288 HRESULT hCom = E_FAIL; 00289 DWORD dwRet; 00290 00291 TRACE("(%p)\n", pTi); 00292 00293 /* We are now executing in the context of the newly created thread. 00294 * So we copy the data passed to us (it is on the stack of the function 00295 * that called us, which is waiting for us to signal an event before 00296 * returning). */ 00297 memcpy(&ti, pTi, sizeof(SHLWAPI_THREAD_INFO)); 00298 00299 /* Initialise COM for the thread, if desired */ 00300 if (ti.bInitCom) 00301 { 00302 hCom = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED|COINIT_DISABLE_OLE1DDE); 00303 00304 if (FAILED(hCom)) 00305 hCom = CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE); 00306 } 00307 00308 /* Execute the callback function before returning */ 00309 if (ti.pfnCallback) 00310 ti.pfnCallback(ti.pData); 00311 00312 /* Signal the thread that created us; it can return now */ 00313 SetEvent(ti.hEvent); 00314 00315 /* Execute the callers start code */ 00316 dwRet = ti.pfnThreadProc(ti.pData); 00317 00318 /* Release references to the caller and IE process, if held */ 00319 if (ti.refThread) 00320 IUnknown_Release(ti.refThread); 00321 00322 if (ti.refIE) 00323 IUnknown_Release(ti.refIE); 00324 00325 if (SUCCEEDED(hCom)) 00326 CoUninitialize(); 00327 00328 /* Return the users thread return value */ 00329 return dwRet; 00330 } 00331 00332 /************************************************************************* 00333 * SHCreateThread [SHLWAPI.16] 00334 * 00335 * Create a new thread. 00336 * 00337 * PARAMS 00338 * pfnThreadProc [I] Function to execute in new thread 00339 * pData [I] Application specific data passed to pfnThreadProc 00340 * dwFlags [I] CTF_ flags from "shlwapi.h" 00341 * pfnCallback [I] Function to execute before pfnThreadProc 00342 * 00343 * RETURNS 00344 * Success: TRUE. pfnThreadProc was executed. 00345 * Failure: FALSE. pfnThreadProc was not executed. 00346 * 00347 * NOTES 00348 * If the thread cannot be created, pfnCallback is NULL, and dwFlags 00349 * has bit CTF_INSIST set, pfnThreadProc will be executed synchronously. 00350 */ 00351 BOOL WINAPI SHCreateThread(LPTHREAD_START_ROUTINE pfnThreadProc, VOID *pData, 00352 DWORD dwFlags, LPTHREAD_START_ROUTINE pfnCallback) 00353 { 00354 SHLWAPI_THREAD_INFO ti; 00355 BOOL bCalled = FALSE; 00356 00357 TRACE("(%p,%p,0x%X,%p)\n", pfnThreadProc, pData, dwFlags, pfnCallback); 00358 00359 /* Set up data to pass to the new thread (On our stack) */ 00360 ti.pfnThreadProc = pfnThreadProc; 00361 ti.pfnCallback = pfnCallback; 00362 ti.pData = pData; 00363 ti.bInitCom = dwFlags & CTF_COINIT ? TRUE : FALSE; 00364 ti.hEvent = CreateEventW(NULL,FALSE,FALSE,NULL); 00365 00366 /* Hold references to the current thread and IE process, if desired */ 00367 if(dwFlags & CTF_THREAD_REF) 00368 SHGetThreadRef(&ti.refThread); 00369 else 00370 ti.refThread = NULL; 00371 00372 if(dwFlags & CTF_PROCESS_REF) 00373 _SHGetInstanceExplorer(&ti.refIE); 00374 else 00375 ti.refIE = NULL; 00376 00377 /* Create the thread */ 00378 if(ti.hEvent) 00379 { 00380 DWORD dwRetVal; 00381 HANDLE hThread; 00382 00383 hThread = CreateThread(NULL, 0, SHLWAPI_ThreadWrapper, &ti, 0, &dwRetVal); 00384 00385 if(hThread) 00386 { 00387 /* Wait for the thread to signal us to continue */ 00388 WaitForSingleObject(ti.hEvent, INFINITE); 00389 CloseHandle(hThread); 00390 bCalled = TRUE; 00391 } 00392 CloseHandle(ti.hEvent); 00393 } 00394 00395 if (!bCalled) 00396 { 00397 if (!ti.pfnCallback && dwFlags & CTF_INSIST) 00398 { 00399 /* Couldn't call, call synchronously */ 00400 pfnThreadProc(pData); 00401 bCalled = TRUE; 00402 } 00403 else 00404 { 00405 /* Free references, since thread hasn't run to do so */ 00406 if(ti.refThread) 00407 IUnknown_Release(ti.refThread); 00408 00409 if(ti.refIE) 00410 IUnknown_Release(ti.refIE); 00411 } 00412 } 00413 return bCalled; 00414 } 00415 00416 /************************************************************************* 00417 * SHGlobalCounterGetValue [SHLWAPI.223] 00418 * 00419 * Get the current count of a semaphore. 00420 * 00421 * PARAMS 00422 * hSem [I] Semaphore handle 00423 * 00424 * RETURNS 00425 * The current count of the semaphore. 00426 */ 00427 LONG WINAPI SHGlobalCounterGetValue(HANDLE hSem) 00428 { 00429 LONG dwOldCount = 0; 00430 00431 TRACE("(%p)\n", hSem); 00432 ReleaseSemaphore(hSem, 1, &dwOldCount); /* +1 */ 00433 WaitForSingleObject(hSem, 0); /* -1 */ 00434 return dwOldCount; 00435 } 00436 00437 /************************************************************************* 00438 * SHGlobalCounterIncrement [SHLWAPI.224] 00439 * 00440 * Claim a semaphore. 00441 * 00442 * PARAMS 00443 * hSem [I] Semaphore handle 00444 * 00445 * RETURNS 00446 * The new count of the semaphore. 00447 */ 00448 LONG WINAPI SHGlobalCounterIncrement(HANDLE hSem) 00449 { 00450 LONG dwOldCount = 0; 00451 00452 TRACE("(%p)\n", hSem); 00453 ReleaseSemaphore(hSem, 1, &dwOldCount); 00454 return dwOldCount + 1; 00455 } 00456 00457 /************************************************************************* 00458 * SHGlobalCounterDecrement [SHLWAPI.424] 00459 * 00460 * Release a semaphore. 00461 * 00462 * PARAMS 00463 * hSem [I] Semaphore handle 00464 * 00465 * RETURNS 00466 * The new count of the semaphore. 00467 */ 00468 DWORD WINAPI SHGlobalCounterDecrement(HANDLE hSem) 00469 { 00470 DWORD dwOldCount = 0; 00471 00472 TRACE("(%p)\n", hSem); 00473 00474 dwOldCount = SHGlobalCounterGetValue(hSem); 00475 WaitForSingleObject(hSem, 0); 00476 return dwOldCount - 1; 00477 } 00478 00479 /************************************************************************* 00480 * SHGlobalCounterCreateNamedW [SHLWAPI.423] 00481 * 00482 * Unicode version of SHGlobalCounterCreateNamedA. 00483 */ 00484 HANDLE WINAPI SHGlobalCounterCreateNamedW(LPCWSTR lpszName, DWORD iInitial) 00485 { 00486 static const WCHAR szPrefix[] = { 's', 'h', 'e', 'l', 'l', '.', '\0' }; 00487 const int iPrefixLen = 6; 00488 WCHAR szBuff[MAX_PATH]; 00489 const int iBuffLen = sizeof(szBuff)/sizeof(WCHAR); 00490 SECURITY_DESCRIPTOR sd; 00491 SECURITY_ATTRIBUTES sAttr, *pSecAttr; 00492 HANDLE hRet; 00493 00494 TRACE("(%s,%d)\n", debugstr_w(lpszName), iInitial); 00495 00496 /* Create Semaphore name */ 00497 memcpy(szBuff, szPrefix, (iPrefixLen + 1) * sizeof(WCHAR)); 00498 if (lpszName) 00499 StrCpyNW(szBuff + iPrefixLen, lpszName, iBuffLen - iPrefixLen); 00500 00501 /* Initialise security attributes */ 00502 pSecAttr = CreateAllAccessSecurityAttributes(&sAttr, &sd, 0); 00503 00504 if (!(hRet = CreateSemaphoreW(pSecAttr , iInitial, MAXLONG, szBuff))) 00505 hRet = OpenSemaphoreW(SYNCHRONIZE|SEMAPHORE_MODIFY_STATE, 0, szBuff); 00506 return hRet; 00507 } 00508 00509 /************************************************************************* 00510 * SHGlobalCounterCreateNamedA [SHLWAPI.422] 00511 * 00512 * Create a semaphore. 00513 * 00514 * PARAMS 00515 * lpszName [I] Name of semaphore 00516 * iInitial [I] Initial count for semaphore 00517 * 00518 * RETURNS 00519 * A new semaphore handle. 00520 */ 00521 HANDLE WINAPI SHGlobalCounterCreateNamedA(LPCSTR lpszName, DWORD iInitial) 00522 { 00523 WCHAR szBuff[MAX_PATH]; 00524 00525 TRACE("(%s,%d)\n", debugstr_a(lpszName), iInitial); 00526 00527 if (lpszName) 00528 MultiByteToWideChar(0, 0, lpszName, -1, szBuff, MAX_PATH); 00529 return SHGlobalCounterCreateNamedW(lpszName ? szBuff : NULL, iInitial); 00530 } 00531 00532 /************************************************************************* 00533 * SHGlobalCounterCreate [SHLWAPI.222] 00534 * 00535 * Create a semaphore using the name of a GUID. 00536 * 00537 * PARAMS 00538 * guid [I] GUID to use as semaphore name 00539 * 00540 * RETURNS 00541 * A handle to the semaphore. 00542 * 00543 * NOTES 00544 * The initial count of the semaphore is set to 0. 00545 */ 00546 HANDLE WINAPI SHGlobalCounterCreate (REFGUID guid) 00547 { 00548 char szName[40]; 00549 00550 TRACE("(%s)\n", debugstr_guid(guid)); 00551 00552 /* Create a named semaphore using the GUID string */ 00553 SHStringFromGUIDA(guid, szName, sizeof(szName) - 1); 00554 return SHGlobalCounterCreateNamedA(szName, 0); 00555 } Generated on Fri May 25 2012 04:22:29 for ReactOS by
1.7.6.1
|