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

thread.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 doxygen 1.7.6.1

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