winepulse: Remove AudioSessionManager.
[wine.git] / dlls / kernelbase / main.c
blob0309ec91589a01f0520d50969884008f80ac2d25
1 /*
2 * Copyright 2016 Michael Müller
3 * Copyright 2017 Andrey Gusev
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define COBJMACROS
22 #include "ntstatus.h"
23 #define WIN32_NO_STATUS
24 #include "windows.h"
25 #include "appmodel.h"
26 #include "shlwapi.h"
27 #include "perflib.h"
28 #include "winternl.h"
30 #include "wine/debug.h"
31 #include "kernelbase.h"
32 #include "wine/heap.h"
33 #include "wine/list.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(kernelbase);
38 BOOL is_wow64 = FALSE;
40 /***********************************************************************
41 * DllMain
43 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
45 if (reason == DLL_PROCESS_ATTACH)
47 DisableThreadLibraryCalls( hinst );
48 IsWow64Process( GetCurrentProcess(), &is_wow64 );
49 init_global_data();
50 init_locale( hinst );
51 init_startup_info( NtCurrentTeb()->Peb->ProcessParameters );
52 init_console();
54 return TRUE;
58 /*************************************************************
59 * DllMainCRTStartup
61 BOOL WINAPI DllMainCRTStartup( HANDLE inst, DWORD reason, LPVOID reserved )
63 return DllMain( inst, reason, reserved );
67 /***********************************************************************
68 * MulDiv (kernelbase.@)
70 INT WINAPI MulDiv( INT a, INT b, INT c )
72 LONGLONG ret;
74 if (!c) return -1;
76 /* We want to deal with a positive divisor to simplify the logic. */
77 if (c < 0)
79 a = -a;
80 c = -c;
83 /* If the result is positive, we "add" to round. else, we subtract to round. */
84 if ((a < 0 && b < 0) || (a >= 0 && b >= 0))
85 ret = (((LONGLONG)a * b) + (c / 2)) / c;
86 else
87 ret = (((LONGLONG)a * b) - (c / 2)) / c;
89 if (ret > 2147483647 || ret < -2147483647) return -1;
90 return ret;
93 /***********************************************************************
94 * AppPolicyGetMediaFoundationCodecLoading (KERNELBASE.@)
97 LONG WINAPI AppPolicyGetMediaFoundationCodecLoading(HANDLE token, AppPolicyMediaFoundationCodecLoading *policy)
99 FIXME("%p, %p\n", token, policy);
101 if(policy)
102 *policy = AppPolicyMediaFoundationCodecLoading_All;
104 return ERROR_SUCCESS;
107 /***********************************************************************
108 * AppPolicyGetProcessTerminationMethod (KERNELBASE.@)
110 LONG WINAPI AppPolicyGetProcessTerminationMethod(HANDLE token, AppPolicyProcessTerminationMethod *policy)
112 FIXME("%p, %p\n", token, policy);
114 if(policy)
115 *policy = AppPolicyProcessTerminationMethod_ExitProcess;
117 return ERROR_SUCCESS;
120 /***********************************************************************
121 * AppPolicyGetThreadInitializationType (KERNELBASE.@)
123 LONG WINAPI AppPolicyGetThreadInitializationType(HANDLE token, AppPolicyThreadInitializationType *policy)
125 FIXME("%p, %p\n", token, policy);
127 if(policy)
128 *policy = AppPolicyThreadInitializationType_None;
130 return ERROR_SUCCESS;
133 /***********************************************************************
134 * AppPolicyGetShowDeveloperDiagnostic (KERNELBASE.@)
136 LONG WINAPI AppPolicyGetShowDeveloperDiagnostic(HANDLE token, AppPolicyShowDeveloperDiagnostic *policy)
138 FIXME("%p, %p\n", token, policy);
140 if(policy)
141 *policy = AppPolicyShowDeveloperDiagnostic_ShowUI;
143 return ERROR_SUCCESS;
146 /***********************************************************************
147 * AppPolicyGetWindowingModel (KERNELBASE.@)
149 LONG WINAPI AppPolicyGetWindowingModel(HANDLE token, AppPolicyWindowingModel *policy)
151 FIXME("%p, %p\n", token, policy);
153 if(policy)
154 *policy = AppPolicyWindowingModel_ClassicDesktop;
156 return ERROR_SUCCESS;
159 struct counterset_template
161 PERF_COUNTERSET_INFO counterset;
162 PERF_COUNTER_INFO counter[1];
165 struct counterset_instance
167 struct list entry;
168 struct counterset_template *template;
169 PERF_COUNTERSET_INSTANCE instance;
172 struct perf_provider
174 GUID guid;
175 PERFLIBREQUEST callback;
176 struct counterset_template **countersets;
177 unsigned int counterset_count;
179 struct list instance_list;
182 static struct perf_provider *perf_provider_from_handle(HANDLE prov)
184 return (struct perf_provider *)prov;
187 /***********************************************************************
188 * PerfCreateInstance (KERNELBASE.@)
190 PERF_COUNTERSET_INSTANCE WINAPI *PerfCreateInstance( HANDLE handle, const GUID *guid,
191 const WCHAR *name, ULONG id )
193 struct perf_provider *prov = perf_provider_from_handle( handle );
194 struct counterset_template *template;
195 struct counterset_instance *inst;
196 unsigned int i;
197 ULONG size;
199 FIXME( "handle %p, guid %s, name %s, id %lu semi-stub.\n", handle, debugstr_guid(guid), debugstr_w(name), id );
201 if (!prov || !guid || !name)
203 SetLastError( ERROR_INVALID_PARAMETER );
204 return NULL;
207 for (i = 0; i < prov->counterset_count; ++i)
208 if (IsEqualGUID(guid, &prov->countersets[i]->counterset.CounterSetGuid)) break;
210 if (i == prov->counterset_count)
212 SetLastError( ERROR_NOT_FOUND );
213 return NULL;
216 template = prov->countersets[i];
218 LIST_FOR_EACH_ENTRY(inst, &prov->instance_list, struct counterset_instance, entry)
220 if (inst->template == template && inst->instance.InstanceId == id)
222 SetLastError( ERROR_ALREADY_EXISTS );
223 return NULL;
227 size = (sizeof(PERF_COUNTERSET_INSTANCE) + template->counterset.NumCounters * sizeof(UINT64)
228 + (lstrlenW( name ) + 1) * sizeof(WCHAR) + 7) & ~7;
229 inst = heap_alloc_zero( offsetof(struct counterset_instance, instance) + size );
230 if (!inst)
232 SetLastError( ERROR_OUTOFMEMORY );
233 return NULL;
236 inst->template = template;
237 inst->instance.CounterSetGuid = *guid;
238 inst->instance.dwSize = size;
239 inst->instance.InstanceId = id;
240 inst->instance.InstanceNameOffset = sizeof(PERF_COUNTERSET_INSTANCE)
241 + template->counterset.NumCounters * sizeof(UINT64);
242 inst->instance.InstanceNameSize = (lstrlenW( name ) + 1) * sizeof(WCHAR);
243 memcpy( (BYTE *)&inst->instance + inst->instance.InstanceNameOffset, name, inst->instance.InstanceNameSize );
244 list_add_tail( &prov->instance_list, &inst->entry );
246 return &inst->instance;
249 /***********************************************************************
250 * PerfDeleteInstance (KERNELBASE.@)
252 ULONG WINAPI PerfDeleteInstance(HANDLE provider, PERF_COUNTERSET_INSTANCE *block)
254 struct perf_provider *prov = perf_provider_from_handle( provider );
255 struct counterset_instance *inst;
257 TRACE( "provider %p, block %p.\n", provider, block );
259 if (!prov || !block) return ERROR_INVALID_PARAMETER;
261 inst = CONTAINING_RECORD(block, struct counterset_instance, instance);
262 list_remove( &inst->entry );
263 heap_free( inst );
265 return ERROR_SUCCESS;
268 /***********************************************************************
269 * PerfSetCounterSetInfo (KERNELBASE.@)
271 ULONG WINAPI PerfSetCounterSetInfo( HANDLE handle, PERF_COUNTERSET_INFO *template, ULONG size )
273 struct perf_provider *prov = perf_provider_from_handle( handle );
274 struct counterset_template **new_array;
275 struct counterset_template *new;
276 unsigned int i;
278 FIXME( "handle %p, template %p, size %lu semi-stub.\n", handle, template, size );
280 if (!prov || !template) return ERROR_INVALID_PARAMETER;
281 if (!template->NumCounters) return ERROR_INVALID_PARAMETER;
282 if (size < sizeof(*template) || (size - (sizeof(*template))) / sizeof(PERF_COUNTER_INFO) < template->NumCounters)
283 return ERROR_INVALID_PARAMETER;
285 for (i = 0; i < prov->counterset_count; ++i)
287 if (IsEqualGUID( &template->CounterSetGuid, &prov->countersets[i]->counterset.CounterSetGuid ))
288 return ERROR_ALREADY_EXISTS;
291 size = offsetof( struct counterset_template, counter[template->NumCounters] );
292 if (!(new = heap_alloc( size ))) return ERROR_OUTOFMEMORY;
294 if (prov->counterset_count)
295 new_array = heap_realloc( prov->countersets, sizeof(*prov->countersets) * (prov->counterset_count + 1) );
296 else
297 new_array = heap_alloc( sizeof(*prov->countersets) );
299 if (!new_array)
301 heap_free( new );
302 return ERROR_OUTOFMEMORY;
304 memcpy( new, template, size );
305 for (i = 0; i < template->NumCounters; ++i)
306 new->counter[i].Offset = i * sizeof(UINT64);
307 new_array[prov->counterset_count++] = new;
308 prov->countersets = new_array;
310 return STATUS_SUCCESS;
313 /***********************************************************************
314 * PerfSetCounterRefValue (KERNELBASE.@)
316 ULONG WINAPI PerfSetCounterRefValue(HANDLE provider, PERF_COUNTERSET_INSTANCE *instance,
317 ULONG counterid, void *address)
319 struct perf_provider *prov = perf_provider_from_handle( provider );
320 struct counterset_template *template;
321 struct counterset_instance *inst;
322 unsigned int i;
324 FIXME( "provider %p, instance %p, counterid %lu, address %p semi-stub.\n",
325 provider, instance, counterid, address );
327 if (!prov || !instance || !address) return ERROR_INVALID_PARAMETER;
329 inst = CONTAINING_RECORD(instance, struct counterset_instance, instance);
330 template = inst->template;
332 for (i = 0; i < template->counterset.NumCounters; ++i)
333 if (template->counter[i].CounterId == counterid) break;
335 if (i == template->counterset.NumCounters) return ERROR_NOT_FOUND;
336 *(void **)((BYTE *)&inst->instance + sizeof(PERF_COUNTERSET_INSTANCE) + template->counter[i].Offset) = address;
338 return STATUS_SUCCESS;
341 /***********************************************************************
342 * PerfStartProvider (KERNELBASE.@)
344 ULONG WINAPI PerfStartProvider( GUID *guid, PERFLIBREQUEST callback, HANDLE *provider )
346 PERF_PROVIDER_CONTEXT ctx;
348 FIXME( "guid %s, callback %p, provider %p semi-stub.\n", debugstr_guid(guid), callback, provider );
350 memset( &ctx, 0, sizeof(ctx) );
351 ctx.ContextSize = sizeof(ctx);
352 ctx.ControlCallback = callback;
354 return PerfStartProviderEx( guid, &ctx, provider );
357 /***********************************************************************
358 * PerfStartProviderEx (KERNELBASE.@)
360 ULONG WINAPI PerfStartProviderEx( GUID *guid, PERF_PROVIDER_CONTEXT *context, HANDLE *provider )
362 struct perf_provider *prov;
364 FIXME( "guid %s, context %p, provider %p semi-stub.\n", debugstr_guid(guid), context, provider );
366 if (!guid || !context || !provider) return ERROR_INVALID_PARAMETER;
367 if (context->ContextSize < sizeof(*context)) return ERROR_INVALID_PARAMETER;
369 if (context->MemAllocRoutine || context->MemFreeRoutine)
370 FIXME("Memory allocation routine is not supported.\n");
372 if (!(prov = heap_alloc_zero( sizeof(*prov) ))) return ERROR_OUTOFMEMORY;
373 list_init( &prov->instance_list );
374 memcpy( &prov->guid, guid, sizeof(prov->guid) );
375 prov->callback = context->ControlCallback;
376 *provider = prov;
378 return STATUS_SUCCESS;
381 /***********************************************************************
382 * PerfStopProvider (KERNELBASE.@)
384 ULONG WINAPI PerfStopProvider(HANDLE handle)
386 struct perf_provider *prov = perf_provider_from_handle( handle );
387 struct counterset_instance *inst, *next;
388 unsigned int i;
390 TRACE( "handle %p.\n", handle );
392 if (!list_empty( &prov->instance_list ))
393 WARN( "Stopping provider with active counter instances.\n" );
395 LIST_FOR_EACH_ENTRY_SAFE(inst, next, &prov->instance_list, struct counterset_instance, entry)
397 list_remove( &inst->entry );
398 heap_free( inst );
401 for (i = 0; i < prov->counterset_count; ++i)
402 heap_free( prov->countersets[i] );
403 heap_free( prov->countersets );
404 heap_free( prov );
405 return STATUS_SUCCESS;
408 /***********************************************************************
409 * QuirkIsEnabled (KERNELBASE.@)
411 BOOL WINAPI QuirkIsEnabled(void *arg)
413 FIXME("(%p): stub\n", arg);
414 return FALSE;
417 /***********************************************************************
418 * QuirkIsEnabled3 (KERNELBASE.@)
420 BOOL WINAPI QuirkIsEnabled3(void *unk1, void *unk2)
422 static int once;
424 if (!once++)
425 FIXME("(%p, %p) stub!\n", unk1, unk2);
427 return FALSE;
430 HRESULT WINAPI QISearch(void *base, const QITAB *table, REFIID riid, void **obj)
432 const QITAB *ptr;
433 IUnknown *unk;
435 TRACE("%p, %p, %s, %p\n", base, table, debugstr_guid(riid), obj);
437 if (!obj)
438 return E_POINTER;
440 for (ptr = table; ptr->piid; ++ptr)
442 TRACE("trying (offset %ld) %s\n", ptr->dwOffset, debugstr_guid(ptr->piid));
443 if (IsEqualIID(riid, ptr->piid))
445 unk = (IUnknown *)((BYTE *)base + ptr->dwOffset);
446 TRACE("matched, returning (%p)\n", unk);
447 *obj = unk;
448 IUnknown_AddRef(unk);
449 return S_OK;
453 if (IsEqualIID(riid, &IID_IUnknown))
455 unk = (IUnknown *)((BYTE *)base + table->dwOffset);
456 TRACE("returning first for IUnknown (%p)\n", unk);
457 *obj = unk;
458 IUnknown_AddRef(unk);
459 return S_OK;
462 WARN("Not found %s.\n", debugstr_guid(riid));
463 *obj = NULL;
464 return E_NOINTERFACE;
467 HRESULT WINAPI GetAcceptLanguagesA(LPSTR langbuf, DWORD *buflen)
469 DWORD buflenW, convlen;
470 WCHAR *langbufW;
471 HRESULT hr;
473 TRACE("%p, %p, *%p: %ld\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
475 if (!langbuf || !buflen || !*buflen)
476 return E_FAIL;
478 buflenW = *buflen;
479 langbufW = heap_alloc(sizeof(WCHAR) * buflenW);
480 hr = GetAcceptLanguagesW(langbufW, &buflenW);
482 if (hr == S_OK)
484 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf, *buflen, NULL, NULL);
485 convlen--; /* do not count the terminating 0 */
487 else /* copy partial string anyway */
489 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, *buflen, langbuf, *buflen, NULL, NULL);
490 if (convlen < *buflen)
492 langbuf[convlen] = 0;
493 convlen--; /* do not count the terminating 0 */
495 else
497 convlen = *buflen;
500 *buflen = buflenW ? convlen : 0;
502 heap_free(langbufW);
503 return hr;
506 static HRESULT lcid_to_rfc1766(LCID lcid, WCHAR *rfc1766, INT len)
508 WCHAR buffer[6 /* MAX_RFC1766_NAME */];
509 INT n = GetLocaleInfoW(lcid, LOCALE_SISO639LANGNAME, buffer, ARRAY_SIZE(buffer));
510 INT i;
512 if (n)
514 i = PRIMARYLANGID(lcid);
515 if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
516 (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
517 (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
519 buffer[n - 1] = '-';
520 i = GetLocaleInfoW(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, ARRAY_SIZE(buffer) - n);
521 if (!i)
522 buffer[n - 1] = '\0';
524 else
525 i = 0;
527 LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len);
528 return ((n + i) > len) ? E_INVALIDARG : S_OK;
530 return E_FAIL;
533 HRESULT WINAPI GetAcceptLanguagesW(WCHAR *langbuf, DWORD *buflen)
535 DWORD mystrlen, mytype;
536 WCHAR *mystr;
537 LCID mylcid;
538 HKEY mykey;
539 LONG lres;
540 DWORD len;
542 TRACE("%p, %p, *%p: %ld\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
544 if (!langbuf || !buflen || !*buflen)
545 return E_FAIL;
547 mystrlen = (*buflen > 20) ? *buflen : 20 ;
548 len = mystrlen * sizeof(WCHAR);
549 mystr = heap_alloc(len);
550 mystr[0] = 0;
551 RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Internet Explorer\\International",
552 0, KEY_QUERY_VALUE, &mykey);
553 lres = RegQueryValueExW(mykey, L"AcceptLanguage", 0, &mytype, (PBYTE)mystr, &len);
554 RegCloseKey(mykey);
555 len = lstrlenW(mystr);
557 if (!lres && (*buflen > len))
559 lstrcpyW(langbuf, mystr);
560 *buflen = len;
561 heap_free(mystr);
562 return S_OK;
565 /* Did not find a value in the registry or the user buffer is too small */
566 mylcid = GetUserDefaultLCID();
567 lcid_to_rfc1766(mylcid, mystr, mystrlen);
568 len = lstrlenW(mystr);
570 memcpy(langbuf, mystr, min(*buflen, len + 1)*sizeof(WCHAR));
571 heap_free(mystr);
573 if (*buflen > len)
575 *buflen = len;
576 return S_OK;
579 *buflen = 0;
580 return E_NOT_SUFFICIENT_BUFFER;