Prevent crash when no URL is specified.
[wine] / dlls / setupapi / misc.c
1 /*
2  * Setupapi miscellaneous functions
3  *
4  * Copyright 2005 Eric Kohl
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "winreg.h"
28 #include "setupapi.h"
29
30 #include "wine/unicode.h"
31 #include "wine/debug.h"
32
33 #include "setupapi_private.h"
34
35
36 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
37
38
39 /**************************************************************************
40  * MyFree [SETUPAPI.@]
41  *
42  * Frees an allocated memory block from the process heap.
43  *
44  * PARAMS
45  *     lpMem [I] pointer to memory block which will be freed
46  *
47  * RETURNS
48  *     None
49  */
50 VOID WINAPI MyFree(LPVOID lpMem)
51 {
52     TRACE("%p\n", lpMem);
53     HeapFree(GetProcessHeap(), 0, lpMem);
54 }
55
56
57 /**************************************************************************
58  * MyMalloc [SETUPAPI.@]
59  *
60  * Allocates memory block from the process heap.
61  *
62  * PARAMS
63  *     dwSize [I] size of the allocated memory block
64  *
65  * RETURNS
66  *     Success: pointer to allocated memory block
67  *     Failure: NULL
68  */
69 LPVOID WINAPI MyMalloc(DWORD dwSize)
70 {
71     TRACE("%lu\n", dwSize);
72     return HeapAlloc(GetProcessHeap(), 0, dwSize);
73 }
74
75
76 /**************************************************************************
77  * MyRealloc [SETUPAPI.@]
78  *
79  * Changes the size of an allocated memory block or allocates a memory
80  * block from the process heap.
81  *
82  * PARAMS
83  *     lpSrc  [I] pointer to memory block which will be resized
84  *     dwSize [I] new size of the memory block
85  *
86  * RETURNS
87  *     Success: pointer to the resized memory block
88  *     Failure: NULL
89  *
90  * NOTES
91  *     If lpSrc is a NULL-pointer, then MyRealloc allocates a memory
92  *     block like MyMalloc.
93  */
94 LPVOID WINAPI MyRealloc(LPVOID lpSrc, DWORD dwSize)
95 {
96     TRACE("%p %lu\n", lpSrc, dwSize);
97
98     if (lpSrc == NULL)
99         return HeapAlloc(GetProcessHeap(), 0, dwSize);
100
101     return HeapReAlloc(GetProcessHeap(), 0, lpSrc, dwSize);
102 }
103
104
105 /**************************************************************************
106  * DuplicateString [SETUPAPI.@]
107  *
108  * Duplicates a unicode string.
109  *
110  * PARAMS
111  *     lpSrc  [I] pointer to the unicode string that will be duplicated
112  *
113  * RETURNS
114  *     Success: pointer to the duplicated unicode string
115  *     Failure: NULL
116  *
117  * NOTES
118  *     Call MyFree() to release the duplicated string.
119  */
120 LPWSTR WINAPI DuplicateString(LPCWSTR lpSrc)
121 {
122     LPWSTR lpDst;
123
124     TRACE("%s\n", debugstr_w(lpSrc));
125
126     lpDst = MyMalloc((lstrlenW(lpSrc) + 1) * sizeof(WCHAR));
127     if (lpDst == NULL)
128         return NULL;
129
130     strcpyW(lpDst, lpSrc);
131
132     return lpDst;
133 }
134
135
136 /**************************************************************************
137  * QueryRegistryValue [SETUPAPI.@]
138  *
139  * Retrieves value data from the registry and allocates memory for the
140  * value data.
141  *
142  * PARAMS
143  *     hKey        [I] Handle of the key to query
144  *     lpValueName [I] Name of value under hkey to query
145  *     lpData      [O] Destination for the values contents,
146  *     lpType      [O] Destination for the value type
147  *     lpcbData    [O] Destination for the size of data
148  *
149  * RETURNS
150  *     Success: ERROR_SUCCESS
151  *     Failure: Otherwise
152  *
153  * NOTES
154  *     Use MyFree to release the lpData buffer.
155  */
156 LONG WINAPI QueryRegistryValue(HKEY hKey,
157                                LPCWSTR lpValueName,
158                                LPBYTE  *lpData,
159                                LPDWORD lpType,
160                                LPDWORD lpcbData)
161 {
162     LONG lError;
163
164     TRACE("%p %s %p %p %p\n",
165           hKey, debugstr_w(lpValueName), lpData, lpType, lpcbData);
166
167     /* Get required buffer size */
168     *lpcbData = 0;
169     lError = RegQueryValueExW(hKey, lpValueName, 0, lpType, NULL, lpcbData);
170     if (lError != ERROR_SUCCESS)
171         return lError;
172
173     /* Allocate buffer */
174     *lpData = MyMalloc(*lpcbData);
175     if (*lpData == NULL)
176         return ERROR_NOT_ENOUGH_MEMORY;
177
178     /* Query registry value */
179     lError = RegQueryValueExW(hKey, lpValueName, 0, lpType, *lpData, lpcbData);
180     if (lError != ERROR_SUCCESS)
181         MyFree(*lpData);
182
183     return lError;
184 }
185
186
187 /**************************************************************************
188  * IsUserAdmin [SETUPAPI.@]
189  *
190  * Checks whether the current user is a member of the Administrators group.
191  *
192  * PARAMS
193  *     None
194  *
195  * RETURNS
196  *     Success: TRUE
197  *     Failure: FALSE
198  */
199 BOOL WINAPI IsUserAdmin(VOID)
200 {
201     SID_IDENTIFIER_AUTHORITY Authority = {SECURITY_NT_AUTHORITY};
202     HANDLE hToken;
203     DWORD dwSize;
204     PTOKEN_GROUPS lpGroups;
205     PSID lpSid;
206     DWORD i;
207     BOOL bResult = FALSE;
208
209     TRACE("\n");
210
211     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
212     {
213         return FALSE;
214     }
215
216     if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize))
217     {
218         if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
219         {
220             CloseHandle(hToken);
221             return FALSE;
222         }
223     }
224
225     lpGroups = MyMalloc(dwSize);
226     if (lpGroups == NULL)
227     {
228         CloseHandle(hToken);
229         return FALSE;
230     }
231
232     if (!GetTokenInformation(hToken, TokenGroups, lpGroups, dwSize, &dwSize))
233     {
234         MyFree(lpGroups);
235         CloseHandle(hToken);
236         return FALSE;
237     }
238
239     CloseHandle(hToken);
240
241     if (!AllocateAndInitializeSid(&Authority, 2, SECURITY_BUILTIN_DOMAIN_RID,
242                                   DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
243                                   &lpSid))
244     {
245         MyFree(lpGroups);
246         return FALSE;
247     }
248
249     for (i = 0; i < lpGroups->GroupCount; i++)
250     {
251         if (EqualSid(lpSid, &lpGroups->Groups[i].Sid))
252         {
253             bResult = TRUE;
254             break;
255         }
256     }
257
258     FreeSid(lpSid);
259     MyFree(lpGroups);
260
261     return bResult;
262 }
263
264
265 /**************************************************************************
266  * MultiByteToUnicode [SETUPAPI.@]
267  *
268  * Converts a multi-byte string to a Unicode string.
269  *
270  * PARAMS
271  *     lpMultiByteStr  [I] Multi-byte string to be converted
272  *     uCodePage       [I] Code page
273  *
274  * RETURNS
275  *     Success: pointer to the converted Unicode string
276  *     Failure: NULL
277  *
278  * NOTE
279  *     Use MyFree to release the returned Unicode string.
280  */
281 LPWSTR WINAPI MultiByteToUnicode(LPCSTR lpMultiByteStr, UINT uCodePage)
282 {
283     LPWSTR lpUnicodeStr;
284     int nLength;
285
286     TRACE("%s %d\n", debugstr_a(lpMultiByteStr), uCodePage);
287
288     nLength = MultiByteToWideChar(uCodePage, 0, lpMultiByteStr,
289                                   -1, NULL, 0);
290     if (nLength == 0)
291         return NULL;
292
293     lpUnicodeStr = MyMalloc(nLength * sizeof(WCHAR));
294     if (lpUnicodeStr == NULL)
295         return NULL;
296
297     if (!MultiByteToWideChar(uCodePage, 0, lpMultiByteStr,
298                              nLength, lpUnicodeStr, nLength))
299     {
300         MyFree(lpUnicodeStr);
301         return NULL;
302     }
303
304     return lpUnicodeStr;
305 }
306
307
308 /**************************************************************************
309  * UnicodeToMultiByte [SETUPAPI.@]
310  *
311  * Converts a Unicode string to a multi-byte string.
312  *
313  * PARAMS
314  *     lpUnicodeStr  [I] Unicode string to be converted
315  *     uCodePage     [I] Code page
316  *
317  * RETURNS
318  *     Success: pointer to the converted multi-byte string
319  *     Failure: NULL
320  *
321  * NOTE
322  *     Use MyFree to release the returned multi-byte string.
323  */
324 LPSTR WINAPI UnicodeToMultiByte(LPCWSTR lpUnicodeStr, UINT uCodePage)
325 {
326     LPSTR lpMultiByteStr;
327     int nLength;
328
329     TRACE("%s %d\n", debugstr_w(lpUnicodeStr), uCodePage);
330
331     nLength = WideCharToMultiByte(uCodePage, 0, lpUnicodeStr, -1,
332                                   NULL, 0, NULL, NULL);
333     if (nLength == 0)
334         return NULL;
335
336     lpMultiByteStr = MyMalloc(nLength);
337     if (lpMultiByteStr == NULL)
338         return NULL;
339
340     if (!WideCharToMultiByte(uCodePage, 0, lpUnicodeStr, -1,
341                              lpMultiByteStr, nLength, NULL, NULL))
342     {
343         MyFree(lpMultiByteStr);
344         return NULL;
345     }
346
347     return lpMultiByteStr;
348 }
349
350
351 /**************************************************************************
352  * DoesUserHavePrivilege [SETUPAPI.@]
353  *
354  * Check whether the current user has got a given privilege.
355  *
356  * PARAMS
357  *     lpPrivilegeName  [I] Name of the privilege to be checked
358  *
359  * RETURNS
360  *     Success: TRUE
361  *     Failure: FALSE
362  */
363 BOOL WINAPI DoesUserHavePrivilege(LPCWSTR lpPrivilegeName)
364 {
365     HANDLE hToken;
366     DWORD dwSize;
367     PTOKEN_PRIVILEGES lpPrivileges;
368     LUID PrivilegeLuid;
369     DWORD i;
370     BOOL bResult = FALSE;
371
372     TRACE("%s\n", debugstr_w(lpPrivilegeName));
373
374     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
375         return FALSE;
376
377     if (!GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwSize))
378     {
379         if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
380         {
381             CloseHandle(hToken);
382             return FALSE;
383         }
384     }
385
386     lpPrivileges = MyMalloc(dwSize);
387     if (lpPrivileges == NULL)
388     {
389         CloseHandle(hToken);
390         return FALSE;
391     }
392
393     if (!GetTokenInformation(hToken, TokenPrivileges, lpPrivileges, dwSize, &dwSize))
394     {
395         MyFree(lpPrivileges);
396         CloseHandle(hToken);
397         return FALSE;
398     }
399
400     CloseHandle(hToken);
401
402     if (!LookupPrivilegeValueW(NULL, lpPrivilegeName, &PrivilegeLuid))
403     {
404         MyFree(lpPrivileges);
405         return FALSE;
406     }
407
408     for (i = 0; i < lpPrivileges->PrivilegeCount; i++)
409     {
410         if (lpPrivileges->Privileges[i].Luid.HighPart == PrivilegeLuid.HighPart &&
411             lpPrivileges->Privileges[i].Luid.LowPart == PrivilegeLuid.LowPart)
412         {
413             bResult = TRUE;
414         }
415     }
416
417     MyFree(lpPrivileges);
418
419     return bResult;
420 }
421
422
423 /**************************************************************************
424  * EnablePrivilege [SETUPAPI.@]
425  *
426  * Enables or disables one of the current users privileges.
427  *
428  * PARAMS
429  *     lpPrivilegeName  [I] Name of the privilege to be changed
430  *     bEnable          [I] TRUE: Enables the privilege
431  *                          FALSE: Disables the privilege
432  *
433  * RETURNS
434  *     Success: TRUE
435  *     Failure: FALSE
436  */
437 BOOL WINAPI EnablePrivilege(LPCWSTR lpPrivilegeName, BOOL bEnable)
438 {
439     TOKEN_PRIVILEGES Privileges;
440     HANDLE hToken;
441     BOOL bResult;
442
443     TRACE("%s %s\n", debugstr_w(lpPrivilegeName), bEnable ? "TRUE" : "FALSE");
444
445     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
446         return FALSE;
447
448     Privileges.PrivilegeCount = 1;
449     Privileges.Privileges[0].Attributes = (bEnable) ? SE_PRIVILEGE_ENABLED : 0;
450
451     if (!LookupPrivilegeValueW(NULL, lpPrivilegeName,
452                                &Privileges.Privileges[0].Luid))
453     {
454         CloseHandle(hToken);
455         return FALSE;
456     }
457
458     bResult = AdjustTokenPrivileges(hToken, FALSE, &Privileges, 0, NULL, NULL);
459
460     CloseHandle(hToken);
461
462     return bResult;
463 }
464
465
466 BOOL WINAPI DelayedMove(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
467 {
468     return MoveFileExW(lpExistingFileName, lpNewFileName,
469                        MOVEFILE_REPLACE_EXISTING | MOVEFILE_DELAY_UNTIL_REBOOT);
470 }
471
472
473 BOOL WINAPI FileExists(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFileFindData)
474 {
475     WIN32_FIND_DATAW FindData;
476     HANDLE hFind;
477     UINT uErrorMode;
478     DWORD dwError;
479
480     uErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
481
482     hFind = FindFirstFileW(lpFileName, &FindData);
483     if (hFind == INVALID_HANDLE_VALUE)
484     {
485         dwError = GetLastError();
486         SetErrorMode(uErrorMode);
487         SetLastError(dwError);
488         return FALSE;
489     }
490
491     FindClose(hFind);
492
493     if (lpFileFindData)
494         memcpy(lpFileFindData, &FindData, sizeof(WIN32_FIND_DATAW));
495
496     return TRUE;
497 }