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
23 #define WIN32_NO_STATUS
30 #include "wine/debug.h"
31 #include "kernelbase.h"
32 #include "wine/heap.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(kernelbase
);
37 BOOL is_wow64
= FALSE
;
39 /***********************************************************************
42 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
44 if (reason
== DLL_PROCESS_ATTACH
)
46 DisableThreadLibraryCalls( hinst
);
47 IsWow64Process( GetCurrentProcess(), &is_wow64
);
49 init_startup_info( NtCurrentTeb()->Peb
->ProcessParameters
);
56 /*************************************************************
59 BOOL WINAPI
DllMainCRTStartup( HANDLE inst
, DWORD reason
, LPVOID reserved
)
61 return DllMain( inst
, reason
, reserved
);
65 /***********************************************************************
66 * MulDiv (kernelbase.@)
68 INT WINAPI
MulDiv( INT a
, INT b
, INT c
)
74 /* We want to deal with a positive divisor to simplify the logic. */
81 /* If the result is positive, we "add" to round. else, we subtract to round. */
82 if ((a
< 0 && b
< 0) || (a
>= 0 && b
>= 0))
83 ret
= (((LONGLONG
)a
* b
) + (c
/ 2)) / c
;
85 ret
= (((LONGLONG
)a
* b
) - (c
/ 2)) / c
;
87 if (ret
> 2147483647 || ret
< -2147483647) return -1;
91 /***********************************************************************
92 * AppPolicyGetProcessTerminationMethod (KERNELBASE.@)
94 LONG WINAPI
AppPolicyGetProcessTerminationMethod(HANDLE token
, AppPolicyProcessTerminationMethod
*policy
)
96 FIXME("%p, %p\n", token
, policy
);
99 *policy
= AppPolicyProcessTerminationMethod_ExitProcess
;
101 return ERROR_SUCCESS
;
104 /***********************************************************************
105 * AppPolicyGetThreadInitializationType (KERNELBASE.@)
107 LONG WINAPI
AppPolicyGetThreadInitializationType(HANDLE token
, AppPolicyThreadInitializationType
*policy
)
109 FIXME("%p, %p\n", token
, policy
);
112 *policy
= AppPolicyThreadInitializationType_None
;
114 return ERROR_SUCCESS
;
117 /***********************************************************************
118 * AppPolicyGetShowDeveloperDiagnostic (KERNELBASE.@)
120 LONG WINAPI
AppPolicyGetShowDeveloperDiagnostic(HANDLE token
, AppPolicyShowDeveloperDiagnostic
*policy
)
122 FIXME("%p, %p\n", token
, policy
);
125 *policy
= AppPolicyShowDeveloperDiagnostic_ShowUI
;
127 return ERROR_SUCCESS
;
130 /***********************************************************************
131 * AppPolicyGetWindowingModel (KERNELBASE.@)
133 LONG WINAPI
AppPolicyGetWindowingModel(HANDLE token
, AppPolicyWindowingModel
*policy
)
135 FIXME("%p, %p\n", token
, policy
);
138 *policy
= AppPolicyWindowingModel_ClassicDesktop
;
140 return ERROR_SUCCESS
;
143 /***********************************************************************
144 * PerfCreateInstance (KERNELBASE.@)
146 PPERF_COUNTERSET_INSTANCE WINAPI
PerfCreateInstance(HANDLE handle
, LPCGUID guid
,
147 const WCHAR
*name
, ULONG id
)
149 FIXME("%p %s %s %u: stub\n", handle
, debugstr_guid(guid
), debugstr_w(name
), id
);
153 /***********************************************************************
154 * PerfDeleteInstance (KERNELBASE.@)
156 ULONG WINAPI
PerfDeleteInstance(HANDLE provider
, PPERF_COUNTERSET_INSTANCE block
)
158 FIXME("%p %p: stub\n", provider
, block
);
159 return ERROR_CALL_NOT_IMPLEMENTED
;
162 /***********************************************************************
163 * PerfSetCounterSetInfo (KERNELBASE.@)
165 ULONG WINAPI
PerfSetCounterSetInfo(HANDLE handle
, PPERF_COUNTERSET_INFO
template, ULONG size
)
167 FIXME("%p %p %u: stub\n", handle
, template, size
);
168 return ERROR_CALL_NOT_IMPLEMENTED
;
171 /***********************************************************************
172 * PerfSetCounterRefValue (KERNELBASE.@)
174 ULONG WINAPI
PerfSetCounterRefValue(HANDLE provider
, PPERF_COUNTERSET_INSTANCE instance
,
175 ULONG counterid
, void *address
)
177 FIXME("%p %p %u %p: stub\n", provider
, instance
, counterid
, address
);
178 return ERROR_CALL_NOT_IMPLEMENTED
;
181 /***********************************************************************
182 * PerfStartProvider (KERNELBASE.@)
184 ULONG WINAPI
PerfStartProvider(GUID
*guid
, PERFLIBREQUEST callback
, HANDLE
*provider
)
186 FIXME("%s %p %p: stub\n", debugstr_guid(guid
), callback
, provider
);
187 return ERROR_CALL_NOT_IMPLEMENTED
;
190 /***********************************************************************
191 * PerfStartProviderEx (KERNELBASE.@)
193 ULONG WINAPI
PerfStartProviderEx(GUID
*guid
, PPERF_PROVIDER_CONTEXT context
, HANDLE
*provider
)
195 FIXME("%s %p %p: stub\n", debugstr_guid(guid
), context
, provider
);
196 return ERROR_CALL_NOT_IMPLEMENTED
;
199 /***********************************************************************
200 * PerfStopProvider (KERNELBASE.@)
202 ULONG WINAPI
PerfStopProvider(HANDLE handle
)
204 FIXME("%p: stub\n", handle
);
205 return ERROR_CALL_NOT_IMPLEMENTED
;
208 /***********************************************************************
209 * QuirkIsEnabled (KERNELBASE.@)
211 BOOL WINAPI
QuirkIsEnabled(void *arg
)
213 FIXME("(%p): stub\n", arg
);
217 /***********************************************************************
218 * QuirkIsEnabled3 (KERNELBASE.@)
220 BOOL WINAPI
QuirkIsEnabled3(void *unk1
, void *unk2
)
225 FIXME("(%p, %p) stub!\n", unk1
, unk2
);
230 HRESULT WINAPI
QISearch(void *base
, const QITAB
*table
, REFIID riid
, void **obj
)
235 TRACE("%p, %p, %s, %p\n", base
, table
, debugstr_guid(riid
), obj
);
240 for (ptr
= table
; ptr
->piid
; ++ptr
)
242 TRACE("trying (offset %d) %s\n", ptr
->dwOffset
, debugstr_guid(ptr
->piid
));
243 if (IsEqualIID(riid
, ptr
->piid
))
245 unk
= (IUnknown
*)((BYTE
*)base
+ ptr
->dwOffset
);
246 TRACE("matched, returning (%p)\n", unk
);
248 IUnknown_AddRef(unk
);
253 if (IsEqualIID(riid
, &IID_IUnknown
))
255 unk
= (IUnknown
*)((BYTE
*)base
+ table
->dwOffset
);
256 TRACE("returning first for IUnknown (%p)\n", unk
);
258 IUnknown_AddRef(unk
);
262 WARN("Not found %s.\n", debugstr_guid(riid
));
264 return E_NOINTERFACE
;
267 HRESULT WINAPI
GetAcceptLanguagesA(LPSTR langbuf
, DWORD
*buflen
)
269 DWORD buflenW
, convlen
;
273 TRACE("%p, %p, *%p: %d\n", langbuf
, buflen
, buflen
, buflen
? *buflen
: -1);
275 if (!langbuf
|| !buflen
|| !*buflen
)
279 langbufW
= heap_alloc(sizeof(WCHAR
) * buflenW
);
280 hr
= GetAcceptLanguagesW(langbufW
, &buflenW
);
284 convlen
= WideCharToMultiByte(CP_ACP
, 0, langbufW
, -1, langbuf
, *buflen
, NULL
, NULL
);
285 convlen
--; /* do not count the terminating 0 */
287 else /* copy partial string anyway */
289 convlen
= WideCharToMultiByte(CP_ACP
, 0, langbufW
, *buflen
, langbuf
, *buflen
, NULL
, NULL
);
290 if (convlen
< *buflen
)
292 langbuf
[convlen
] = 0;
293 convlen
--; /* do not count the terminating 0 */
300 *buflen
= buflenW
? convlen
: 0;
306 static HRESULT
lcid_to_rfc1766(LCID lcid
, WCHAR
*rfc1766
, INT len
)
308 WCHAR buffer
[6 /* MAX_RFC1766_NAME */];
309 INT n
= GetLocaleInfoW(lcid
, LOCALE_SISO639LANGNAME
, buffer
, ARRAY_SIZE(buffer
));
314 i
= PRIMARYLANGID(lcid
);
315 if ((((i
== LANG_ENGLISH
) || (i
== LANG_CHINESE
) || (i
== LANG_ARABIC
)) &&
316 (SUBLANGID(lcid
) == SUBLANG_DEFAULT
)) ||
317 (SUBLANGID(lcid
) > SUBLANG_DEFAULT
)) {
320 i
= GetLocaleInfoW(lcid
, LOCALE_SISO3166CTRYNAME
, buffer
+ n
, ARRAY_SIZE(buffer
) - n
);
322 buffer
[n
- 1] = '\0';
327 LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
, buffer
, n
+ i
, rfc1766
, len
);
328 return ((n
+ i
) > len
) ? E_INVALIDARG
: S_OK
;
333 HRESULT WINAPI
GetAcceptLanguagesW(WCHAR
*langbuf
, DWORD
*buflen
)
335 DWORD mystrlen
, mytype
;
342 TRACE("%p, %p, *%p: %d\n", langbuf
, buflen
, buflen
, buflen
? *buflen
: -1);
344 if (!langbuf
|| !buflen
|| !*buflen
)
347 mystrlen
= (*buflen
> 20) ? *buflen
: 20 ;
348 len
= mystrlen
* sizeof(WCHAR
);
349 mystr
= heap_alloc(len
);
351 RegOpenKeyExW(HKEY_CURRENT_USER
, L
"Software\\Microsoft\\Internet Explorer\\International",
352 0, KEY_QUERY_VALUE
, &mykey
);
353 lres
= RegQueryValueExW(mykey
, L
"AcceptLanguage", 0, &mytype
, (PBYTE
)mystr
, &len
);
355 len
= lstrlenW(mystr
);
357 if (!lres
&& (*buflen
> len
))
359 lstrcpyW(langbuf
, mystr
);
365 /* Did not find a value in the registry or the user buffer is too small */
366 mylcid
= GetUserDefaultLCID();
367 lcid_to_rfc1766(mylcid
, mystr
, mystrlen
);
368 len
= lstrlenW(mystr
);
370 memcpy(langbuf
, mystr
, min(*buflen
, len
+ 1)*sizeof(WCHAR
));
380 return E_NOT_SUFFICIENT_BUFFER
;