Always print a message for generic stubs.
[wine/dcerpc.git] / dlls / shlwapi / thread.c
blobef090758d6f2223c352ee16f77b14cf4565ce672
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 <stdarg.h>
22 #include <string.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winnls.h"
27 #include "wine/debug.h"
28 #define NO_SHLWAPI_REG
29 #define NO_SHLWAPI_PATH
30 #define NO_SHLWAPI_GDI
31 #define NO_SHLWAPI_STREAM
32 #define NO_SHLWAPI_USER
33 #include "shlwapi.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(shell);
37 /* Get a function pointer from a DLL handle */
38 #define GET_FUNC(func, module, name, fail) \
39 do { \
40 if (!func) { \
41 if (!SHLWAPI_h##module && !(SHLWAPI_h##module = LoadLibraryA(#module ".dll"))) return fail; \
42 if (!(func = (void*)GetProcAddress(SHLWAPI_h##module, name))) return fail; \
43 } \
44 } while (0)
46 /* DLL handles for late bound calls */
47 extern HMODULE SHLWAPI_hshell32;
49 /* Function pointers for GET_FUNC macro; these need to be global because of gcc bug */
50 static HRESULT (WINAPI *pSHGetInstanceExplorer)(IUnknown**);
52 extern DWORD SHLWAPI_ThreadRef_index; /* Initialised in shlwapi_main.c */
54 DWORD WINAPI SHStringFromGUIDA(REFGUID,LPSTR,INT);
56 /**************************************************************************
57 * _CreateAllAccessSecurityAttributes [SHLWAPI.356]
59 * Initialise security attributes from a security descriptor.
61 * PARAMS
62 * lpAttr [O] Security attributes
63 * lpSec [I] Security descriptor
65 * RETURNS
66 * Success: lpAttr, initialised using lpSec.
67 * Failure: NULL, if any parameters are invalid.
69 * NOTES
70 * This function always returns NULL if the underlying OS version
71 * Wine is impersonating does not use security descriptors (i.e. anything
72 * before Windows NT).
74 LPSECURITY_ATTRIBUTES WINAPI _CreateAllAccessSecurityAttributes(
75 LPSECURITY_ATTRIBUTES lpAttr,
76 PSECURITY_DESCRIPTOR lpSec)
78 /* This function is used within SHLWAPI only to create security attributes
79 * for shell semaphores. */
81 TRACE("(%p,%p)\n", lpAttr, lpSec);
83 if (!(GetVersion() & 0x80000000)) /* NT */
85 if (!lpSec || !lpAttr)
86 return NULL;
88 if (InitializeSecurityDescriptor(lpSec, 1))
90 if (SetSecurityDescriptorDacl(lpSec, TRUE, NULL, FALSE))
92 lpAttr->nLength = sizeof(SECURITY_ATTRIBUTES);
93 lpAttr->lpSecurityDescriptor = lpSec;
94 lpAttr->bInheritHandle = FALSE;
95 return lpAttr;
99 return NULL;
102 /*************************************************************************
103 * _SHGetInstanceExplorer [SHLWAPI.@]
105 * Get an interface to the shell explorer.
107 * PARAMS
108 * lppUnknown [O] Destination for explorers IUnknown interface.
110 * RETURNS
111 * Success: S_OK. lppUnknown contains the explorer interface.
112 * Failure: An HRESULT error code.
114 HRESULT WINAPI _SHGetInstanceExplorer(IUnknown **lppUnknown)
116 /* This function is used within SHLWAPI only to hold the IE reference
117 * for threads created with the CTF_PROCESS_REF flag set. */
119 GET_FUNC(pSHGetInstanceExplorer, shell32, "SHGetInstanceExplorer", E_FAIL);
120 return pSHGetInstanceExplorer(lppUnknown);
123 /* Internal thread information structure */
124 typedef struct tagSHLWAPI_THREAD_INFO
126 LPTHREAD_START_ROUTINE pfnThreadProc; /* Thread start */
127 LPTHREAD_START_ROUTINE pfnCallback; /* Thread initialisation */
128 PVOID pData; /* Application specific data */
129 BOOL bInitCom; /* Initialise COM for the thread? */
130 HANDLE hEvent; /* Signal for creator to continue */
131 IUnknown *refThread; /* Reference to thread creator */
132 IUnknown *refIE; /* Reference to the IE process */
133 } SHLWAPI_THREAD_INFO, *LPSHLWAPI_THREAD_INFO;
136 /*************************************************************************
137 * SHGetThreadRef [SHLWAPI.@]
139 * Get a per-thread object reference set by SHSetThreadRef().
141 * PARAMS
142 * lppUnknown [O] Destination to receive object reference
144 * RETURNS
145 * Success: S_OK. lppUnknown is set to the object reference.
146 * Failure: E_NOINTERFACE, if an error occurs or lppUnknown is NULL.
148 HRESULT WINAPI SHGetThreadRef(IUnknown **lppUnknown)
150 TRACE("(%p)\n", lppUnknown);
152 if (!lppUnknown || SHLWAPI_ThreadRef_index == TLS_OUT_OF_INDEXES)
153 return E_NOINTERFACE;
155 *lppUnknown = (IUnknown*)TlsGetValue(SHLWAPI_ThreadRef_index);
156 if (!*lppUnknown)
157 return E_NOINTERFACE;
159 /* Add a reference. Caller will Release() us when finished */
160 IUnknown_AddRef(*lppUnknown);
161 return S_OK;
164 /*************************************************************************
165 * SHSetThreadRef [SHLWAPI.@]
167 * Store a per-thread object reference.
169 * PARAMS
170 * lpUnknown [I] Object reference to store
172 * RETURNS
173 * Success: S_OK. lpUnknown is stored and can be retrieved by SHGetThreadRef()
174 * Failure: E_NOINTERFACE, if an error occurs or lpUnknown is NULL.
176 HRESULT WINAPI SHSetThreadRef(IUnknown *lpUnknown)
178 TRACE("(%p)\n", lpUnknown);
180 if (!lpUnknown || SHLWAPI_ThreadRef_index == 0xffffffff)
181 return E_NOINTERFACE;
183 TlsSetValue(SHLWAPI_ThreadRef_index, lpUnknown);
184 return S_OK;
187 /*************************************************************************
188 * SHReleaseThreadRef [SHLWAPI.@]
190 * Release a per-thread object reference.
192 * PARAMS
193 * None.
195 * RETURNS
196 * Success: S_OK. The threads object reference is released.
197 * Failure: An HRESULT error code.
199 HRESULT WINAPI SHReleaseThreadRef()
201 FIXME("() - stub!\n");
202 return S_OK;
205 /*************************************************************************
206 * SHLWAPI_ThreadWrapper
208 * Internal wrapper for executing user thread functions from SHCreateThread.
210 static DWORD WINAPI SHLWAPI_ThreadWrapper(PVOID pTi)
212 SHLWAPI_THREAD_INFO ti;
213 HRESULT hCom = E_FAIL;
214 DWORD dwRet;
216 TRACE("(%p)", pTi);
218 /* We are now executing in the context of the newly created thread.
219 * So we copy the data passed to us (it is on the stack of the function
220 * that called us, which is waiting for us to signal an event before
221 * returning). */
222 memcpy(&ti, pTi, sizeof(SHLWAPI_THREAD_INFO));
224 /* Initialise COM for the thread, if desired */
225 if (ti.bInitCom)
227 hCom = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED|COINIT_DISABLE_OLE1DDE);
229 if (FAILED(hCom))
230 hCom = CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE);
233 /* Execute the callback function before returning */
234 if (ti.pfnCallback)
235 ti.pfnCallback(ti.pData);
237 /* Signal the thread that created us; it can return now */
238 SetEvent(ti.hEvent);
240 /* Execute the callers start code */
241 dwRet = ti.pfnThreadProc(ti.pData);
243 /* Release references to the caller and IE process, if held */
244 if (ti.refThread)
245 IUnknown_Release(ti.refThread);
247 if (ti.refIE)
248 IUnknown_Release(ti.refIE);
250 if (SUCCEEDED(hCom))
251 CoUninitialize();
253 /* Return the users thread return value */
254 return dwRet;
257 /*************************************************************************
258 * SHCreateThread [SHLWAPI.16]
260 * Create a new thread.
262 * PARAMS
263 * pfnThreadProc [I] Function to execute in new thread
264 * pData [I] Application specific data passed to pfnThreadProc
265 * dwFlags [I] CTF_ flags from "shlwapi.h"
266 * pfnCallback [I] Function to execute before pfnThreadProc
268 * RETURNS
269 * Success: TRUE. pfnThreadProc was executed.
270 * Failure: FALSE. pfnThreadProc was not executed.
272 * NOTES
273 * If the thread cannot be created, pfnCallback is NULL, and dwFlags
274 * has bit CTF_INSIST set, pfnThreadProc will be executed synchronously.
276 BOOL WINAPI SHCreateThread(LPTHREAD_START_ROUTINE pfnThreadProc, VOID *pData,
277 DWORD dwFlags, LPTHREAD_START_ROUTINE pfnCallback)
279 SHLWAPI_THREAD_INFO ti;
280 BOOL bCalled = FALSE;
282 TRACE("(%p,%p,0x%lX,%p)\n", pfnThreadProc, pData, dwFlags, pfnCallback);
284 /* Set up data to pass to the new thread (On our stack) */
285 ti.pfnThreadProc = pfnThreadProc;
286 ti.pfnCallback = pfnCallback;
287 ti.pData = pData;
288 ti.bInitCom = dwFlags & CTF_COINIT ? TRUE : FALSE;
289 ti.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
291 /* Hold references to the current thread and IE process, if desired */
292 if(dwFlags & CTF_THREAD_REF)
293 SHGetThreadRef(&ti.refThread);
294 else
295 ti.refThread = NULL;
297 if(dwFlags & CTF_PROCESS_REF)
298 _SHGetInstanceExplorer(&ti.refIE);
299 else
300 ti.refIE = NULL;
302 /* Create the thread */
303 if(ti.hEvent)
305 DWORD dwRetVal;
306 HANDLE hThread;
308 hThread = CreateThread(NULL, 0, SHLWAPI_ThreadWrapper, &ti, 0, &dwRetVal);
310 if(hThread)
312 /* Wait for the thread to signal us to continue */
313 WaitForSingleObject(ti.hEvent, -1);
314 CloseHandle(hThread);
315 bCalled = TRUE;
317 CloseHandle(ti.hEvent);
320 if (!bCalled)
322 if (!ti.pfnCallback && dwFlags & CTF_INSIST)
324 /* Couldn't call, call synchronously */
325 pfnThreadProc(pData);
326 bCalled = TRUE;
328 else
330 /* Free references, since thread hasn't run to do so */
331 if(ti.refThread)
332 IUnknown_Release(ti.refThread);
334 if(ti.refIE)
335 IUnknown_Release(ti.refIE);
338 return bCalled;
341 /*************************************************************************
342 * _SHGlobalCounterGetValue [SHLWAPI.223]
344 * Get the current count of a semaphore.
346 * PARAMS
347 * hSem [I] Semaphore handle
349 * RETURNS
350 * The current count of the semaphore.
352 LONG WINAPI _SHGlobalCounterGetValue(HANDLE hSem)
354 LONG dwOldCount = 0;
356 TRACE("(%p)\n", hSem);
357 ReleaseSemaphore(hSem, 1, &dwOldCount); /* +1 */
358 WaitForSingleObject(hSem, 0); /* -1 */
359 return dwOldCount;
362 /*************************************************************************
363 * _SHGlobalCounterIncrement [SHLWAPI.224]
365 * Claim a semaphore.
367 * PARAMS
368 * hSem [I] Semaphore handle
370 * RETURNS
371 * The new count of the semaphore.
373 LONG WINAPI _SHGlobalCounterIncrement(HANDLE hSem)
375 LONG dwOldCount = 0;
377 TRACE("(%p)\n", hSem);
378 ReleaseSemaphore(hSem, 1, &dwOldCount);
379 return dwOldCount + 1;
382 /*************************************************************************
383 * _SHGlobalCounterDecrement [SHLWAPI.424]
385 * Release a semaphore.
387 * PARAMS
388 * hSem [I] Semaphore handle
390 * RETURNS
391 * The new count of the semaphore.
393 DWORD WINAPI _SHGlobalCounterDecrement(HANDLE hSem)
395 DWORD dwOldCount = 0;
397 TRACE("(%p)\n", hSem);
399 dwOldCount = _SHGlobalCounterGetValue(hSem);
400 WaitForSingleObject(hSem, 0);
401 return dwOldCount - 1;
404 /*************************************************************************
405 * _SHGlobalCounterCreateNamedW [SHLWAPI.423]
407 * Unicode version of _SHGlobalCounterCreateNamedA.
409 HANDLE WINAPI _SHGlobalCounterCreateNamedW(LPCWSTR lpszName, DWORD iInitial)
411 static const WCHAR szPrefix[] = { 's', 'h', 'e', 'l', 'l', '.', '\0' };
412 const int iPrefixLen = 6;
413 WCHAR szBuff[MAX_PATH];
414 const int iBuffLen = sizeof(szBuff)/sizeof(WCHAR);
415 SECURITY_DESCRIPTOR sd;
416 SECURITY_ATTRIBUTES sAttr, *pSecAttr;
417 HANDLE hRet;
419 TRACE("(%s,%ld)\n", debugstr_w(lpszName), iInitial);
421 /* Create Semaphore name */
422 memcpy(szBuff, szPrefix, (iPrefixLen + 1) * sizeof(WCHAR));
423 if (lpszName)
424 StrCpyNW(szBuff + iPrefixLen, lpszName, iBuffLen - iPrefixLen);
426 /* Initialise security attributes */
427 pSecAttr = _CreateAllAccessSecurityAttributes(&sAttr, &sd);
429 if (!(hRet = CreateSemaphoreW(pSecAttr , iInitial, MAXLONG, szBuff)))
430 hRet = OpenSemaphoreW(SYNCHRONIZE|SEMAPHORE_MODIFY_STATE, 0, szBuff);
431 return hRet;
434 /*************************************************************************
435 * _SHGlobalCounterCreateNamedA [SHLWAPI.422]
437 * Create a semaphore.
439 * PARAMS
440 * lpszName [I] Name of semaphore
441 * iInitial [I] Initial count for semaphore
443 * RETURNS
444 * A new semaphore handle.
446 HANDLE WINAPI _SHGlobalCounterCreateNamedA(LPCSTR lpszName, DWORD iInitial)
448 WCHAR szBuff[MAX_PATH];
450 TRACE("(%s,%ld)\n", debugstr_a(lpszName), iInitial);
452 if (lpszName)
453 MultiByteToWideChar(0, 0, lpszName, -1, szBuff, MAX_PATH);
454 return _SHGlobalCounterCreateNamedW(lpszName ? szBuff : NULL, iInitial);
457 /*************************************************************************
458 * _SHGlobalCounterCreate [SHLWAPI.222]
460 * Create a semaphore using the name of a GUID.
462 * PARAMS
463 * guid [I] GUID to use as semaphore name
465 * RETURNS
466 * A handle to the semaphore.
468 * NOTES
469 * The initial count of the semaphore is set to 0.
471 HANDLE WINAPI _SHGlobalCounterCreate (REFGUID guid)
473 char szName[40];
475 TRACE("(%s)\n", debugstr_guid(guid));
477 /* Create a named semaphore using the GUID string */
478 SHStringFromGUIDA(guid, szName, sizeof(szName) - 1);
479 return _SHGlobalCounterCreateNamedA(szName, 0);