blob: 00d26f78eb75d77e4b3983c46956c5a14859434b [file] [log] [blame]
Jon Griffithsd84875c2002-07-22 20:32:53 +00001/*
2 * SHLWAPI thread and MT synchronisation functions
3 *
4 * Copyright 2002 Juergen Schmied
5 * Copyright 2002 Jon Griffiths
6 *
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.
11 *
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.
16 *
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
Jonathan Ernst360a3f92006-05-18 14:49:52 +020019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Jon Griffithsd84875c2002-07-22 20:32:53 +000020 */
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000021#include <stdarg.h>
Jon Griffithsd84875c2002-07-22 20:32:53 +000022#include <string.h>
23
Francois Gouget486d0202004-10-07 03:06:48 +000024#define COBJMACROS
25
Jon Griffithsd84875c2002-07-22 20:32:53 +000026#include "windef.h"
Alexandre Julliard864ca062003-08-20 18:22:31 +000027#include "winbase.h"
Jon Griffithsd84875c2002-07-22 20:32:53 +000028#include "winnls.h"
Dmitry Timoshkov03e9e5b2007-03-28 20:13:54 +090029#include "winuser.h"
Jon Griffithsd84875c2002-07-22 20:32:53 +000030#define NO_SHLWAPI_REG
31#define NO_SHLWAPI_PATH
32#define NO_SHLWAPI_GDI
33#define NO_SHLWAPI_STREAM
34#define NO_SHLWAPI_USER
35#include "shlwapi.h"
Dmitry Timoshkov03e9e5b2007-03-28 20:13:54 +090036#include "shlobj.h"
37#include "wine/debug.h"
Jon Griffithsd84875c2002-07-22 20:32:53 +000038
39WINE_DEFAULT_DEBUG_CHANNEL(shell);
40
Jon Griffiths91ec8e12002-09-20 19:41:08 +000041extern DWORD SHLWAPI_ThreadRef_index; /* Initialised in shlwapi_main.c */
42
Andrew Talbot0110f9e2007-04-14 13:48:21 +010043INT WINAPI SHStringFromGUIDA(REFGUID,LPSTR,INT);
Jon Griffithsd84875c2002-07-22 20:32:53 +000044
45/**************************************************************************
Dmitry Timoshkovc20bf692007-10-26 18:31:55 +090046 * CreateAllAccessSecurityAttributes [SHLWAPI.356]
Jon Griffithsd84875c2002-07-22 20:32:53 +000047 *
48 * Initialise security attributes from a security descriptor.
49 *
50 * PARAMS
51 * lpAttr [O] Security attributes
52 * lpSec [I] Security descriptor
53 *
54 * RETURNS
55 * Success: lpAttr, initialised using lpSec.
56 * Failure: NULL, if any parameters are invalid.
57 *
58 * NOTES
Andreas Mohr114b6672003-04-02 01:23:43 +000059 * This function always returns NULL if the underlying OS version
Jon Griffithsd84875c2002-07-22 20:32:53 +000060 * Wine is impersonating does not use security descriptors (i.e. anything
61 * before Windows NT).
62 */
Dmitry Timoshkovc20bf692007-10-26 18:31:55 +090063LPSECURITY_ATTRIBUTES WINAPI CreateAllAccessSecurityAttributes(
Juergen Schmiedd5281fd2003-01-15 00:53:39 +000064 LPSECURITY_ATTRIBUTES lpAttr,
Huw Davies88a8ff02005-08-09 20:34:57 +000065 PSECURITY_DESCRIPTOR lpSec,
66 DWORD p3)
Jon Griffithsd84875c2002-07-22 20:32:53 +000067{
68 /* This function is used within SHLWAPI only to create security attributes
69 * for shell semaphores. */
70
Hans Leidekkere119a042006-10-06 12:43:28 +020071 TRACE("(%p,%p,%08x)\n", lpAttr, lpSec, p3);
Jon Griffithsd84875c2002-07-22 20:32:53 +000072
Jon Griffithsc2acc922002-08-19 23:56:15 +000073 if (!(GetVersion() & 0x80000000)) /* NT */
Jon Griffithsd84875c2002-07-22 20:32:53 +000074 {
75 if (!lpSec || !lpAttr)
76 return NULL;
77
78 if (InitializeSecurityDescriptor(lpSec, 1))
79 {
80 if (SetSecurityDescriptorDacl(lpSec, TRUE, NULL, FALSE))
81 {
82 lpAttr->nLength = sizeof(SECURITY_ATTRIBUTES);
83 lpAttr->lpSecurityDescriptor = lpSec;
84 lpAttr->bInheritHandle = FALSE;
85 return lpAttr;
86 }
87 }
88 }
89 return NULL;
90}
91
92/*************************************************************************
93 * _SHGetInstanceExplorer [SHLWAPI.@]
94 *
95 * Get an interface to the shell explorer.
96 *
97 * PARAMS
Jon Griffiths46e92102003-07-18 22:55:39 +000098 * lppUnknown [O] Destination for explorers IUnknown interface.
Jon Griffithsd84875c2002-07-22 20:32:53 +000099 *
100 * RETURNS
101 * Success: S_OK. lppUnknown contains the explorer interface.
102 * Failure: An HRESULT error code.
103 */
104HRESULT WINAPI _SHGetInstanceExplorer(IUnknown **lppUnknown)
105{
106 /* This function is used within SHLWAPI only to hold the IE reference
107 * for threads created with the CTF_PROCESS_REF flag set. */
Dmitry Timoshkov03e9e5b2007-03-28 20:13:54 +0900108 return SHGetInstanceExplorer(lppUnknown);
Jon Griffithsd84875c2002-07-22 20:32:53 +0000109}
110
111/* Internal thread information structure */
112typedef struct tagSHLWAPI_THREAD_INFO
113{
114 LPTHREAD_START_ROUTINE pfnThreadProc; /* Thread start */
115 LPTHREAD_START_ROUTINE pfnCallback; /* Thread initialisation */
116 PVOID pData; /* Application specific data */
117 BOOL bInitCom; /* Initialise COM for the thread? */
118 HANDLE hEvent; /* Signal for creator to continue */
119 IUnknown *refThread; /* Reference to thread creator */
120 IUnknown *refIE; /* Reference to the IE process */
121} SHLWAPI_THREAD_INFO, *LPSHLWAPI_THREAD_INFO;
122
Detlef Riekenbergbb1ca6e2010-04-19 23:26:48 +0200123typedef struct
124{
125 const IUnknownVtbl* lpVtbl;
126 LONG *ref;
127} threadref;
128
129static HRESULT WINAPI threadref_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppvObj)
130{
131 threadref * This = (threadref *)iface;
132
133 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppvObj);
134
135 if (ppvObj == NULL)
136 return E_POINTER;
137
138 if (IsEqualGUID(&IID_IUnknown, riid)) {
139 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppvObj);
140 *ppvObj = This;
141 IUnknown_AddRef((IUnknown*)*ppvObj);
142 return S_OK;
143 }
144
145 *ppvObj = NULL;
146 FIXME("(%p, %s, %p) interface not supported\n", This, debugstr_guid(riid), ppvObj);
147 return E_NOINTERFACE;
148}
149
150static ULONG WINAPI threadref_AddRef(IUnknown *iface)
151{
152 threadref * This = (threadref *)iface;
153
154 TRACE("(%p)\n", This);
155 return InterlockedIncrement(This->ref);
156}
157
158static ULONG WINAPI threadref_Release(IUnknown *iface)
159{
160 LONG refcount;
161 threadref * This = (threadref *)iface;
162
163 TRACE("(%p)\n", This);
164
165 refcount = InterlockedDecrement(This->ref);
166 if (!refcount)
167 HeapFree(GetProcessHeap(), 0, This);
168
169 return refcount;
170}
171
172/* VTable */
173static const IUnknownVtbl threadref_vt =
174{
175 threadref_QueryInterface,
176 threadref_AddRef,
177 threadref_Release,
178};
179
180/*************************************************************************
181 * SHCreateThreadRef [SHLWAPI.@]
182 *
183 * Create a per-thread IUnknown object
184 *
185 * PARAMS
186 * lprefcount [I] Pointer to a LONG to be used as refcount
187 * lppUnknown [O] Destination to receive the created object reference
188 *
189 * RETURNS
190 * Success: S_OK. lppUnknown is set to the object reference.
191 * Failure: E_INVALIDARG, if a parameter is NULL
192 */
193HRESULT WINAPI SHCreateThreadRef(LONG *lprefcount, IUnknown **lppUnknown)
194{
195 threadref * This;
196 TRACE("(%p, %p)\n", lprefcount, lppUnknown);
197
198 if (!lprefcount || !lppUnknown)
199 return E_INVALIDARG;
200
201 This = HeapAlloc(GetProcessHeap(), 0, sizeof(threadref));
202 This->lpVtbl = &threadref_vt;
203 This->ref = lprefcount;
204
205 *lprefcount = 1;
206 *lppUnknown = (IUnknown *) This;
207 TRACE("=> returning S_OK with %p\n", This);
208 return S_OK;
209}
Jon Griffithsd84875c2002-07-22 20:32:53 +0000210
211/*************************************************************************
212 * SHGetThreadRef [SHLWAPI.@]
213 *
Jon Griffiths46e92102003-07-18 22:55:39 +0000214 * Get a per-thread object reference set by SHSetThreadRef().
Jon Griffithsd84875c2002-07-22 20:32:53 +0000215 *
216 * PARAMS
217 * lppUnknown [O] Destination to receive object reference
218 *
219 * RETURNS
Jon Griffithscd4234a2003-03-18 18:35:48 +0000220 * Success: S_OK. lppUnknown is set to the object reference.
Detlef Riekenberga9ac4a12010-04-19 00:45:19 +0200221 * Failure: E_NOINTERFACE, if an error occurs or no object is set
Jon Griffithsd84875c2002-07-22 20:32:53 +0000222 */
223HRESULT WINAPI SHGetThreadRef(IUnknown **lppUnknown)
224{
225 TRACE("(%p)\n", lppUnknown);
226
Detlef Riekenberga9ac4a12010-04-19 00:45:19 +0200227 if (SHLWAPI_ThreadRef_index == TLS_OUT_OF_INDEXES)
Jon Griffithsd84875c2002-07-22 20:32:53 +0000228 return E_NOINTERFACE;
229
Michael Stefaniuc5f55f152008-11-05 23:04:51 +0100230 *lppUnknown = TlsGetValue(SHLWAPI_ThreadRef_index);
Jon Griffithsd84875c2002-07-22 20:32:53 +0000231 if (!*lppUnknown)
232 return E_NOINTERFACE;
233
234 /* Add a reference. Caller will Release() us when finished */
235 IUnknown_AddRef(*lppUnknown);
236 return S_OK;
237}
238
239/*************************************************************************
240 * SHSetThreadRef [SHLWAPI.@]
241 *
242 * Store a per-thread object reference.
243 *
244 * PARAMS
Jon Griffithscd4234a2003-03-18 18:35:48 +0000245 * lpUnknown [I] Object reference to store
Jon Griffithsd84875c2002-07-22 20:32:53 +0000246 *
247 * RETURNS
Jon Griffithscd4234a2003-03-18 18:35:48 +0000248 * Success: S_OK. lpUnknown is stored and can be retrieved by SHGetThreadRef()
Detlef Riekenberga9ac4a12010-04-19 00:45:19 +0200249 * Failure: E_NOINTERFACE, if an error occurs
Jon Griffithsd84875c2002-07-22 20:32:53 +0000250 */
251HRESULT WINAPI SHSetThreadRef(IUnknown *lpUnknown)
252{
253 TRACE("(%p)\n", lpUnknown);
254
Detlef Riekenberga9ac4a12010-04-19 00:45:19 +0200255 if (SHLWAPI_ThreadRef_index == TLS_OUT_OF_INDEXES)
Jon Griffithsd84875c2002-07-22 20:32:53 +0000256 return E_NOINTERFACE;
257
258 TlsSetValue(SHLWAPI_ThreadRef_index, lpUnknown);
259 return S_OK;
260}
261
262/*************************************************************************
263 * SHReleaseThreadRef [SHLWAPI.@]
264 *
265 * Release a per-thread object reference.
266 *
267 * PARAMS
268 * None.
269 *
270 * RETURNS
Jon Griffiths46e92102003-07-18 22:55:39 +0000271 * Success: S_OK. The threads object reference is released.
Jon Griffithsd84875c2002-07-22 20:32:53 +0000272 * Failure: An HRESULT error code.
273 */
Francois Gouget29937852007-08-29 21:42:28 +0200274HRESULT WINAPI SHReleaseThreadRef(void)
Jon Griffithsd84875c2002-07-22 20:32:53 +0000275{
276 FIXME("() - stub!\n");
277 return S_OK;
278}
279
280/*************************************************************************
281 * SHLWAPI_ThreadWrapper
282 *
283 * Internal wrapper for executing user thread functions from SHCreateThread.
284 */
285static DWORD WINAPI SHLWAPI_ThreadWrapper(PVOID pTi)
286{
287 SHLWAPI_THREAD_INFO ti;
288 HRESULT hCom = E_FAIL;
289 DWORD dwRet;
290
Francois Gouget6b6ed722004-01-27 00:01:43 +0000291 TRACE("(%p)\n", pTi);
Jon Griffithsd84875c2002-07-22 20:32:53 +0000292
293 /* We are now executing in the context of the newly created thread.
294 * So we copy the data passed to us (it is on the stack of the function
295 * that called us, which is waiting for us to signal an event before
296 * returning). */
297 memcpy(&ti, pTi, sizeof(SHLWAPI_THREAD_INFO));
298
299 /* Initialise COM for the thread, if desired */
300 if (ti.bInitCom)
301 {
302 hCom = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED|COINIT_DISABLE_OLE1DDE);
303
304 if (FAILED(hCom))
305 hCom = CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE);
306 }
307
308 /* Execute the callback function before returning */
309 if (ti.pfnCallback)
310 ti.pfnCallback(ti.pData);
311
312 /* Signal the thread that created us; it can return now */
313 SetEvent(ti.hEvent);
314
315 /* Execute the callers start code */
316 dwRet = ti.pfnThreadProc(ti.pData);
317
318 /* Release references to the caller and IE process, if held */
319 if (ti.refThread)
320 IUnknown_Release(ti.refThread);
321
322 if (ti.refIE)
323 IUnknown_Release(ti.refIE);
324
325 if (SUCCEEDED(hCom))
326 CoUninitialize();
327
328 /* Return the users thread return value */
329 return dwRet;
330}
331
332/*************************************************************************
Jon Griffithscd4234a2003-03-18 18:35:48 +0000333 * SHCreateThread [SHLWAPI.16]
Jon Griffithsd84875c2002-07-22 20:32:53 +0000334 *
335 * Create a new thread.
336 *
337 * PARAMS
338 * pfnThreadProc [I] Function to execute in new thread
339 * pData [I] Application specific data passed to pfnThreadProc
Jon Griffiths46e92102003-07-18 22:55:39 +0000340 * dwFlags [I] CTF_ flags from "shlwapi.h"
Jon Griffithsd84875c2002-07-22 20:32:53 +0000341 * pfnCallback [I] Function to execute before pfnThreadProc
342 *
343 * RETURNS
344 * Success: TRUE. pfnThreadProc was executed.
345 * Failure: FALSE. pfnThreadProc was not executed.
346 *
347 * NOTES
348 * If the thread cannot be created, pfnCallback is NULL, and dwFlags
349 * has bit CTF_INSIST set, pfnThreadProc will be executed synchronously.
350 */
351BOOL WINAPI SHCreateThread(LPTHREAD_START_ROUTINE pfnThreadProc, VOID *pData,
352 DWORD dwFlags, LPTHREAD_START_ROUTINE pfnCallback)
353{
354 SHLWAPI_THREAD_INFO ti;
355 BOOL bCalled = FALSE;
356
Hans Leidekkere119a042006-10-06 12:43:28 +0200357 TRACE("(%p,%p,0x%X,%p)\n", pfnThreadProc, pData, dwFlags, pfnCallback);
Jon Griffithsd84875c2002-07-22 20:32:53 +0000358
359 /* Set up data to pass to the new thread (On our stack) */
360 ti.pfnThreadProc = pfnThreadProc;
361 ti.pfnCallback = pfnCallback;
362 ti.pData = pData;
363 ti.bInitCom = dwFlags & CTF_COINIT ? TRUE : FALSE;
Mike McCormack4a0f9992005-01-07 15:40:09 +0000364 ti.hEvent = CreateEventW(NULL,FALSE,FALSE,NULL);
Jon Griffithsd84875c2002-07-22 20:32:53 +0000365
366 /* Hold references to the current thread and IE process, if desired */
367 if(dwFlags & CTF_THREAD_REF)
368 SHGetThreadRef(&ti.refThread);
369 else
370 ti.refThread = NULL;
371
372 if(dwFlags & CTF_PROCESS_REF)
373 _SHGetInstanceExplorer(&ti.refIE);
374 else
375 ti.refIE = NULL;
376
377 /* Create the thread */
378 if(ti.hEvent)
379 {
380 DWORD dwRetVal;
381 HANDLE hThread;
382
383 hThread = CreateThread(NULL, 0, SHLWAPI_ThreadWrapper, &ti, 0, &dwRetVal);
384
385 if(hThread)
386 {
387 /* Wait for the thread to signal us to continue */
Francois Gougetc6c109a2004-04-09 19:03:13 +0000388 WaitForSingleObject(ti.hEvent, INFINITE);
Jon Griffithsd84875c2002-07-22 20:32:53 +0000389 CloseHandle(hThread);
390 bCalled = TRUE;
391 }
392 CloseHandle(ti.hEvent);
393 }
394
395 if (!bCalled)
396 {
397 if (!ti.pfnCallback && dwFlags & CTF_INSIST)
398 {
399 /* Couldn't call, call synchronously */
400 pfnThreadProc(pData);
401 bCalled = TRUE;
402 }
403 else
404 {
405 /* Free references, since thread hasn't run to do so */
406 if(ti.refThread)
407 IUnknown_Release(ti.refThread);
408
409 if(ti.refIE)
410 IUnknown_Release(ti.refIE);
411 }
412 }
413 return bCalled;
414}
415
416/*************************************************************************
Dmitry Timoshkovc20bf692007-10-26 18:31:55 +0900417 * SHGlobalCounterGetValue [SHLWAPI.223]
Jon Griffithsd84875c2002-07-22 20:32:53 +0000418 *
419 * Get the current count of a semaphore.
420 *
421 * PARAMS
422 * hSem [I] Semaphore handle
423 *
424 * RETURNS
425 * The current count of the semaphore.
426 */
Dmitry Timoshkovc20bf692007-10-26 18:31:55 +0900427LONG WINAPI SHGlobalCounterGetValue(HANDLE hSem)
Jon Griffithsd84875c2002-07-22 20:32:53 +0000428{
Jon Griffiths46e92102003-07-18 22:55:39 +0000429 LONG dwOldCount = 0;
Jon Griffithsd84875c2002-07-22 20:32:53 +0000430
Michael Stefaniuc79404212002-10-25 03:12:32 +0000431 TRACE("(%p)\n", hSem);
Jon Griffithsd84875c2002-07-22 20:32:53 +0000432 ReleaseSemaphore(hSem, 1, &dwOldCount); /* +1 */
433 WaitForSingleObject(hSem, 0); /* -1 */
434 return dwOldCount;
435}
436
437/*************************************************************************
Dmitry Timoshkovc20bf692007-10-26 18:31:55 +0900438 * SHGlobalCounterIncrement [SHLWAPI.224]
Jon Griffithsd84875c2002-07-22 20:32:53 +0000439 *
440 * Claim a semaphore.
441 *
442 * PARAMS
443 * hSem [I] Semaphore handle
444 *
445 * RETURNS
446 * The new count of the semaphore.
447 */
Dmitry Timoshkovc20bf692007-10-26 18:31:55 +0900448LONG WINAPI SHGlobalCounterIncrement(HANDLE hSem)
Jon Griffithsd84875c2002-07-22 20:32:53 +0000449{
Jon Griffiths46e92102003-07-18 22:55:39 +0000450 LONG dwOldCount = 0;
Jon Griffithsd84875c2002-07-22 20:32:53 +0000451
Michael Stefaniuc79404212002-10-25 03:12:32 +0000452 TRACE("(%p)\n", hSem);
Jon Griffithsd84875c2002-07-22 20:32:53 +0000453 ReleaseSemaphore(hSem, 1, &dwOldCount);
454 return dwOldCount + 1;
455}
456
457/*************************************************************************
Dmitry Timoshkovc20bf692007-10-26 18:31:55 +0900458 * SHGlobalCounterDecrement [SHLWAPI.424]
Jon Griffithsd84875c2002-07-22 20:32:53 +0000459 *
460 * Release a semaphore.
461 *
462 * PARAMS
463 * hSem [I] Semaphore handle
464 *
465 * RETURNS
466 * The new count of the semaphore.
467 */
Dmitry Timoshkovc20bf692007-10-26 18:31:55 +0900468DWORD WINAPI SHGlobalCounterDecrement(HANDLE hSem)
Jon Griffithsd84875c2002-07-22 20:32:53 +0000469{
470 DWORD dwOldCount = 0;
471
Michael Stefaniuc79404212002-10-25 03:12:32 +0000472 TRACE("(%p)\n", hSem);
Jon Griffithsd84875c2002-07-22 20:32:53 +0000473
Dmitry Timoshkovc20bf692007-10-26 18:31:55 +0900474 dwOldCount = SHGlobalCounterGetValue(hSem);
Jon Griffithsd84875c2002-07-22 20:32:53 +0000475 WaitForSingleObject(hSem, 0);
476 return dwOldCount - 1;
477}
478
479/*************************************************************************
Dmitry Timoshkovc20bf692007-10-26 18:31:55 +0900480 * SHGlobalCounterCreateNamedW [SHLWAPI.423]
Jon Griffithsd84875c2002-07-22 20:32:53 +0000481 *
Dmitry Timoshkovc20bf692007-10-26 18:31:55 +0900482 * Unicode version of SHGlobalCounterCreateNamedA.
Jon Griffithsd84875c2002-07-22 20:32:53 +0000483 */
Dmitry Timoshkovc20bf692007-10-26 18:31:55 +0900484HANDLE WINAPI SHGlobalCounterCreateNamedW(LPCWSTR lpszName, DWORD iInitial)
Jon Griffithsd84875c2002-07-22 20:32:53 +0000485{
486 static const WCHAR szPrefix[] = { 's', 'h', 'e', 'l', 'l', '.', '\0' };
487 const int iPrefixLen = 6;
488 WCHAR szBuff[MAX_PATH];
489 const int iBuffLen = sizeof(szBuff)/sizeof(WCHAR);
490 SECURITY_DESCRIPTOR sd;
491 SECURITY_ATTRIBUTES sAttr, *pSecAttr;
492 HANDLE hRet;
493
Hans Leidekkere119a042006-10-06 12:43:28 +0200494 TRACE("(%s,%d)\n", debugstr_w(lpszName), iInitial);
Jon Griffithsd84875c2002-07-22 20:32:53 +0000495
496 /* Create Semaphore name */
497 memcpy(szBuff, szPrefix, (iPrefixLen + 1) * sizeof(WCHAR));
498 if (lpszName)
499 StrCpyNW(szBuff + iPrefixLen, lpszName, iBuffLen - iPrefixLen);
500
501 /* Initialise security attributes */
Dmitry Timoshkovc20bf692007-10-26 18:31:55 +0900502 pSecAttr = CreateAllAccessSecurityAttributes(&sAttr, &sd, 0);
Jon Griffithsd84875c2002-07-22 20:32:53 +0000503
504 if (!(hRet = CreateSemaphoreW(pSecAttr , iInitial, MAXLONG, szBuff)))
505 hRet = OpenSemaphoreW(SYNCHRONIZE|SEMAPHORE_MODIFY_STATE, 0, szBuff);
506 return hRet;
507}
508
509/*************************************************************************
Dmitry Timoshkovc20bf692007-10-26 18:31:55 +0900510 * SHGlobalCounterCreateNamedA [SHLWAPI.422]
Jon Griffithsd84875c2002-07-22 20:32:53 +0000511 *
512 * Create a semaphore.
513 *
514 * PARAMS
515 * lpszName [I] Name of semaphore
516 * iInitial [I] Initial count for semaphore
517 *
518 * RETURNS
519 * A new semaphore handle.
520 */
Dmitry Timoshkovc20bf692007-10-26 18:31:55 +0900521HANDLE WINAPI SHGlobalCounterCreateNamedA(LPCSTR lpszName, DWORD iInitial)
Jon Griffithsd84875c2002-07-22 20:32:53 +0000522{
523 WCHAR szBuff[MAX_PATH];
524
Hans Leidekkere119a042006-10-06 12:43:28 +0200525 TRACE("(%s,%d)\n", debugstr_a(lpszName), iInitial);
Jon Griffithsd84875c2002-07-22 20:32:53 +0000526
527 if (lpszName)
528 MultiByteToWideChar(0, 0, lpszName, -1, szBuff, MAX_PATH);
Dmitry Timoshkovc20bf692007-10-26 18:31:55 +0900529 return SHGlobalCounterCreateNamedW(lpszName ? szBuff : NULL, iInitial);
Jon Griffithsd84875c2002-07-22 20:32:53 +0000530}
531
532/*************************************************************************
Dmitry Timoshkovc20bf692007-10-26 18:31:55 +0900533 * SHGlobalCounterCreate [SHLWAPI.222]
Jon Griffithsd84875c2002-07-22 20:32:53 +0000534 *
535 * Create a semaphore using the name of a GUID.
536 *
537 * PARAMS
538 * guid [I] GUID to use as semaphore name
539 *
540 * RETURNS
541 * A handle to the semaphore.
542 *
543 * NOTES
544 * The initial count of the semaphore is set to 0.
545 */
Dmitry Timoshkovc20bf692007-10-26 18:31:55 +0900546HANDLE WINAPI SHGlobalCounterCreate (REFGUID guid)
Jon Griffithsd84875c2002-07-22 20:32:53 +0000547{
548 char szName[40];
549
550 TRACE("(%s)\n", debugstr_guid(guid));
551
552 /* Create a named semaphore using the GUID string */
Robert Shearmanb6f34d32003-09-11 02:56:15 +0000553 SHStringFromGUIDA(guid, szName, sizeof(szName) - 1);
Dmitry Timoshkovc20bf692007-10-26 18:31:55 +0900554 return SHGlobalCounterCreateNamedA(szName, 0);
Jon Griffithsd84875c2002-07-22 20:32:53 +0000555}