Release 20030408.
[wine/gsoc-2012-control.git] / dlls / shlwapi / thread.c
blobcfd40bb5144797e37aa3401fc5b75e24604eae22
1 /*
2 * SHLWAPI thread and MT synchronisation functions
4 * Copyright 2002 Juergen Schmied
5 * Copyright 2002 Jon Griffiths
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <string.h>
23 #include "windef.h"
24 #include "winnls.h"
25 #include "wine/debug.h"
26 #define NO_SHLWAPI_REG
27 #define NO_SHLWAPI_PATH
28 #define NO_SHLWAPI_GDI
29 #define NO_SHLWAPI_STREAM
30 #define NO_SHLWAPI_USER
31 #include "shlwapi.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(shell);
35 /* Get a function pointer from a DLL handle */
36 #define GET_FUNC(func, module, name, fail) \
37 do { \
38 if (!func) { \
39 if (!SHLWAPI_h##module && !(SHLWAPI_h##module = LoadLibraryA(#module ".dll"))) return fail; \
40 if (!(func = (void*)GetProcAddress(SHLWAPI_h##module, name))) return fail; \
41 } \
42 } while (0)
44 /* DLL handles for late bound calls */
45 extern HMODULE SHLWAPI_hshell32;
47 /* Function pointers for GET_FUNC macro; these need to be global because of gcc bug */
48 static HRESULT (WINAPI *pSHGetInstanceExplorer)(IUnknown**);
50 extern DWORD SHLWAPI_ThreadRef_index; /* Initialised in shlwapi_main.c */
52 DWORD WINAPI SHLWAPI_23(REFGUID,LPSTR,INT);
54 /**************************************************************************
55 * _CreateAllAccessSecurityAttributes [SHLWAPI.356]
57 * Initialise security attributes from a security descriptor.
59 * PARAMS
60 * lpAttr [O] Security attributes
61 * lpSec [I] Security descriptor
63 * RETURNS
64 * Success: lpAttr, initialised using lpSec.
65 * Failure: NULL, if any parameters are invalid.
67 * NOTES
68 * This function always returns NULL if the underlying OS version
69 * Wine is impersonating does not use security descriptors (i.e. anything
70 * before Windows NT).
72 LPSECURITY_ATTRIBUTES
73 WINAPI _CreateAllAccessSecurityAttributes(
74 LPSECURITY_ATTRIBUTES lpAttr,
75 PSECURITY_DESCRIPTOR lpSec)
77 /* This function is used within SHLWAPI only to create security attributes
78 * for shell semaphores. */
80 TRACE("(%p,%p)\n", lpAttr, lpSec);
82 if (!(GetVersion() & 0x80000000)) /* NT */
84 if (!lpSec || !lpAttr)
85 return NULL;
87 if (InitializeSecurityDescriptor(lpSec, 1))
89 if (SetSecurityDescriptorDacl(lpSec, TRUE, NULL, FALSE))
91 lpAttr->nLength = sizeof(SECURITY_ATTRIBUTES);
92 lpAttr->lpSecurityDescriptor = lpSec;
93 lpAttr->bInheritHandle = FALSE;
94 return lpAttr;
98 return NULL;
101 /*************************************************************************
102 * _SHGetInstanceExplorer [SHLWAPI.@]
104 * Get an interface to the shell explorer.
106 * PARAMS
107 * lppUnknown [O] pointer to recieve IUnknown interface.
109 * RETURNS
110 * Success: S_OK. lppUnknown contains the explorer interface.
111 * Failure: An HRESULT error code.
113 HRESULT WINAPI _SHGetInstanceExplorer(IUnknown **lppUnknown)
115 /* This function is used within SHLWAPI only to hold the IE reference
116 * for threads created with the CTF_PROCESS_REF flag set. */
118 GET_FUNC(pSHGetInstanceExplorer, shell32, "SHGetInstanceExplorer", E_FAIL);
119 return pSHGetInstanceExplorer(lppUnknown);
122 /* Internal thread information structure */
123 typedef struct tagSHLWAPI_THREAD_INFO
125 LPTHREAD_START_ROUTINE pfnThreadProc; /* Thread start */
126 LPTHREAD_START_ROUTINE pfnCallback; /* Thread initialisation */
127 PVOID pData; /* Application specific data */
128 BOOL bInitCom; /* Initialise COM for the thread? */
129 HANDLE hEvent; /* Signal for creator to continue */
130 IUnknown *refThread; /* Reference to thread creator */
131 IUnknown *refIE; /* Reference to the IE process */
132 } SHLWAPI_THREAD_INFO, *LPSHLWAPI_THREAD_INFO;
135 /*************************************************************************
136 * SHGetThreadRef [SHLWAPI.@]
138 * Get a per-thread object reference set by SHSetThreadRef.
140 * PARAMS
141 * lppUnknown [O] Destination to receive object reference
143 * RETURNS
144 * Success: S_OK. lppUnknown is set to the object reference.
145 * Failure: E_NOINTERFACE, if an error occurs or lppUnknown is NULL.
147 HRESULT WINAPI SHGetThreadRef(IUnknown **lppUnknown)
149 TRACE("(%p)\n", lppUnknown);
151 if (!lppUnknown || SHLWAPI_ThreadRef_index == -1u)
152 return E_NOINTERFACE;
154 *lppUnknown = (IUnknown*)TlsGetValue(SHLWAPI_ThreadRef_index);
155 if (!*lppUnknown)
156 return E_NOINTERFACE;
158 /* Add a reference. Caller will Release() us when finished */
159 IUnknown_AddRef(*lppUnknown);
160 return S_OK;
163 /*************************************************************************
164 * SHSetThreadRef [SHLWAPI.@]
166 * Store a per-thread object reference.
168 * PARAMS
169 * lpUnknown [I] Object reference to store
171 * RETURNS
172 * Success: S_OK. lpUnknown is stored and can be retrieved by SHGetThreadRef()
173 * Failure: E_NOINTERFACE, if an error occurs or lpUnknown is NULL.
175 HRESULT WINAPI SHSetThreadRef(IUnknown *lpUnknown)
177 TRACE("(%p)\n", lpUnknown);
179 if (!lpUnknown || SHLWAPI_ThreadRef_index == 0xffffffff)
180 return E_NOINTERFACE;
182 TlsSetValue(SHLWAPI_ThreadRef_index, lpUnknown);
183 return S_OK;
186 /*************************************************************************
187 * SHReleaseThreadRef [SHLWAPI.@]
189 * Release a per-thread object reference.
191 * PARAMS
192 * None.
194 * RETURNS
195 * Success: S_OK. The threads obbject reference is released.
196 * Failure: An HRESULT error code.
198 HRESULT WINAPI SHReleaseThreadRef()
200 FIXME("() - stub!\n");
201 return S_OK;
204 /*************************************************************************
205 * SHLWAPI_ThreadWrapper
207 * Internal wrapper for executing user thread functions from SHCreateThread.
209 static DWORD WINAPI SHLWAPI_ThreadWrapper(PVOID pTi)
211 SHLWAPI_THREAD_INFO ti;
212 HRESULT hCom = E_FAIL;
213 DWORD dwRet;
215 TRACE("(%p)", pTi);
217 /* We are now executing in the context of the newly created thread.
218 * So we copy the data passed to us (it is on the stack of the function
219 * that called us, which is waiting for us to signal an event before
220 * returning). */
221 memcpy(&ti, pTi, sizeof(SHLWAPI_THREAD_INFO));
223 /* Initialise COM for the thread, if desired */
224 if (ti.bInitCom)
226 hCom = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED|COINIT_DISABLE_OLE1DDE);
228 if (FAILED(hCom))
229 hCom = CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE);
232 /* Execute the callback function before returning */
233 if (ti.pfnCallback)
234 ti.pfnCallback(ti.pData);
236 /* Signal the thread that created us; it can return now */
237 SetEvent(ti.hEvent);
239 /* Execute the callers start code */
240 dwRet = ti.pfnThreadProc(ti.pData);
242 /* Release references to the caller and IE process, if held */
243 if (ti.refThread)
244 IUnknown_Release(ti.refThread);
246 if (ti.refIE)
247 IUnknown_Release(ti.refIE);
249 if (SUCCEEDED(hCom))
250 CoUninitialize();
252 /* Return the users thread return value */
253 return dwRet;
256 /*************************************************************************
257 * SHCreateThread [SHLWAPI.16]
259 * Create a new thread.
261 * PARAMS
262 * pfnThreadProc [I] Function to execute in new thread
263 * pData [I] Application specific data passed to pfnThreadProc
264 * dwFlags [I] Initialisation to perform in the new thread
265 * pfnCallback [I] Function to execute before pfnThreadProc
267 * RETURNS
268 * Success: TRUE. pfnThreadProc was executed.
269 * Failure: FALSE. pfnThreadProc was not executed.
271 * NOTES
272 * If the thread cannot be created, pfnCallback is NULL, and dwFlags
273 * has bit CTF_INSIST set, pfnThreadProc will be executed synchronously.
275 BOOL WINAPI SHCreateThread(LPTHREAD_START_ROUTINE pfnThreadProc, VOID *pData,
276 DWORD dwFlags, LPTHREAD_START_ROUTINE pfnCallback)
278 SHLWAPI_THREAD_INFO ti;
279 BOOL bCalled = FALSE;
281 TRACE("(%p,%p,0x%lX,%p)\n", pfnThreadProc, pData, dwFlags, pfnCallback);
283 /* Set up data to pass to the new thread (On our stack) */
284 ti.pfnThreadProc = pfnThreadProc;
285 ti.pfnCallback = pfnCallback;
286 ti.pData = pData;
287 ti.bInitCom = dwFlags & CTF_COINIT ? TRUE : FALSE;
288 ti.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
290 /* Hold references to the current thread and IE process, if desired */
291 if(dwFlags & CTF_THREAD_REF)
292 SHGetThreadRef(&ti.refThread);
293 else
294 ti.refThread = NULL;
296 if(dwFlags & CTF_PROCESS_REF)
297 _SHGetInstanceExplorer(&ti.refIE);
298 else
299 ti.refIE = NULL;
301 /* Create the thread */
302 if(ti.hEvent)
304 DWORD dwRetVal;
305 HANDLE hThread;
307 hThread = CreateThread(NULL, 0, SHLWAPI_ThreadWrapper, &ti, 0, &dwRetVal);
309 if(hThread)
311 /* Wait for the thread to signal us to continue */
312 WaitForSingleObject(ti.hEvent, -1);
313 CloseHandle(hThread);
314 bCalled = TRUE;
316 CloseHandle(ti.hEvent);
319 if (!bCalled)
321 if (!ti.pfnCallback && dwFlags & CTF_INSIST)
323 /* Couldn't call, call synchronously */
324 pfnThreadProc(pData);
325 bCalled = TRUE;
327 else
329 /* Free references, since thread hasn't run to do so */
330 if(ti.refThread)
331 IUnknown_Release(ti.refThread);
333 if(ti.refIE)
334 IUnknown_Release(ti.refIE);
337 return bCalled;
340 /*************************************************************************
341 * _SHGlobalCounterGetValue [SHLWAPI.223]
343 * Get the current count of a semaphore.
345 * PARAMS
346 * hSem [I] Semaphore handle
348 * RETURNS
349 * The current count of the semaphore.
351 DWORD WINAPI _SHGlobalCounterGetValue(HANDLE hSem)
353 DWORD dwOldCount = 0;
355 TRACE("(%p)\n", hSem);
356 ReleaseSemaphore(hSem, 1, &dwOldCount); /* +1 */
357 WaitForSingleObject(hSem, 0); /* -1 */
358 return dwOldCount;
361 /*************************************************************************
362 * _SHGlobalCounterIncrement [SHLWAPI.224]
364 * Claim a semaphore.
366 * PARAMS
367 * hSem [I] Semaphore handle
369 * RETURNS
370 * The new count of the semaphore.
372 DWORD WINAPI _SHGlobalCounterIncrement(HANDLE hSem)
374 DWORD dwOldCount = 0;
376 TRACE("(%p)\n", hSem);
377 ReleaseSemaphore(hSem, 1, &dwOldCount);
378 return dwOldCount + 1;
381 /*************************************************************************
382 * _SHGlobalCounterDecrement [SHLWAPI.424]
384 * Release a semaphore.
386 * PARAMS
387 * hSem [I] Semaphore handle
389 * RETURNS
390 * The new count of the semaphore.
392 DWORD WINAPI _SHGlobalCounterDecrement(HANDLE hSem)
394 DWORD dwOldCount = 0;
396 TRACE("(%p)\n", hSem);
398 dwOldCount = _SHGlobalCounterGetValue(hSem);
399 WaitForSingleObject(hSem, 0);
400 return dwOldCount - 1;
403 /*************************************************************************
404 * _SHGlobalCounterCreateNamedW [SHLWAPI.423]
406 * Unicode version of _SHGlobalCounterCreateNamedA.
408 HANDLE WINAPI _SHGlobalCounterCreateNamedW(LPCWSTR lpszName, DWORD iInitial)
410 static const WCHAR szPrefix[] = { 's', 'h', 'e', 'l', 'l', '.', '\0' };
411 const int iPrefixLen = 6;
412 WCHAR szBuff[MAX_PATH];
413 const int iBuffLen = sizeof(szBuff)/sizeof(WCHAR);
414 SECURITY_DESCRIPTOR sd;
415 SECURITY_ATTRIBUTES sAttr, *pSecAttr;
416 HANDLE hRet;
418 TRACE("(%s,%ld)\n", debugstr_w(lpszName), iInitial);
420 /* Create Semaphore name */
421 memcpy(szBuff, szPrefix, (iPrefixLen + 1) * sizeof(WCHAR));
422 if (lpszName)
423 StrCpyNW(szBuff + iPrefixLen, lpszName, iBuffLen - iPrefixLen);
425 /* Initialise security attributes */
426 pSecAttr = _CreateAllAccessSecurityAttributes(&sAttr, &sd);
428 if (!(hRet = CreateSemaphoreW(pSecAttr , iInitial, MAXLONG, szBuff)))
429 hRet = OpenSemaphoreW(SYNCHRONIZE|SEMAPHORE_MODIFY_STATE, 0, szBuff);
430 return hRet;
433 /*************************************************************************
434 * _SHGlobalCounterCreateNamedA [SHLWAPI.422]
436 * Create a semaphore.
438 * PARAMS
439 * lpszName [I] Name of semaphore
440 * iInitial [I] Initial count for semaphore
442 * RETURNS
443 * A new semaphore handle.
445 HANDLE WINAPI _SHGlobalCounterCreateNamedA(LPCSTR lpszName, DWORD iInitial)
447 WCHAR szBuff[MAX_PATH];
449 TRACE("(%s,%ld)\n", debugstr_a(lpszName), iInitial);
451 if (lpszName)
452 MultiByteToWideChar(0, 0, lpszName, -1, szBuff, MAX_PATH);
453 return _SHGlobalCounterCreateNamedW(lpszName ? szBuff : NULL, iInitial);
456 /*************************************************************************
457 * _SHGlobalCounterCreate [SHLWAPI.222]
459 * Create a semaphore using the name of a GUID.
461 * PARAMS
462 * guid [I] GUID to use as semaphore name
464 * RETURNS
465 * A handle to the semaphore.
467 * NOTES
468 * The initial count of the semaphore is set to 0.
470 HANDLE WINAPI _SHGlobalCounterCreate (REFGUID guid)
472 char szName[40];
474 TRACE("(%s)\n", debugstr_guid(guid));
476 /* Create a named semaphore using the GUID string */
477 SHLWAPI_23(guid, szName, sizeof(szName) - 1);
478 return _SHGlobalCounterCreateNamedA(szName, 0);