merge ROS Shell without integrated explorer part into trunk
[reactos.git] / reactos / lib / 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("%lx %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 %lu\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 %lu\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 /**************************************************************************
467 * DelayedMove [SETUPAPI.@]
468 *
469 * Moves a file upon the next reboot.
470 *
471 * PARAMS
472 * lpExistingFileName [I] Current file name
473 * lpNewFileName [I] New file name
474 *
475 * RETURNS
476 * Success: TRUE
477 * Failure: FALSE
478 */
479 BOOL WINAPI DelayedMove(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
480 {
481 if (OsVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
482 {
483 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
484 return FALSE;
485 }
486
487 return MoveFileExW(lpExistingFileName, lpNewFileName,
488 MOVEFILE_REPLACE_EXISTING | MOVEFILE_DELAY_UNTIL_REBOOT);
489 }
490
491
492 /**************************************************************************
493 * FileExists [SETUPAPI.@]
494 *
495 * Checks whether a file exists.
496 *
497 * PARAMS
498 * lpFileName [I] Name of the file to check
499 * lpNewFileName [O] Optional information about the existing file
500 *
501 * RETURNS
502 * Success: TRUE
503 * Failure: FALSE
504 */
505 BOOL WINAPI FileExists(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFileFindData)
506 {
507 WIN32_FIND_DATAW FindData;
508 HANDLE hFind;
509 UINT uErrorMode;
510 DWORD dwError;
511
512 uErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
513
514 hFind = FindFirstFileW(lpFileName, &FindData);
515 if (hFind == INVALID_HANDLE_VALUE)
516 {
517 dwError = GetLastError();
518 SetErrorMode(uErrorMode);
519 SetLastError(dwError);
520 return FALSE;
521 }
522
523 FindClose(hFind);
524
525 if (lpFileFindData)
526 memcpy(lpFileFindData, &FindData, sizeof(WIN32_FIND_DATAW));
527
528 SetErrorMode(uErrorMode);
529
530 return TRUE;
531 }
532
533
534 /**************************************************************************
535 * CaptureStringArg [SETUPAPI.@]
536 *
537 * Captures a UNICODE string.
538 *
539 * PARAMS
540 * lpSrc [I] UNICODE string to be captured
541 * lpDst [O] Pointer to the captured UNICODE string
542 *
543 * RETURNS
544 * Success: ERROR_SUCCESS
545 * Failure: ERROR_INVALID_PARAMETER
546 *
547 * NOTE
548 * Call MyFree to release the captured UNICODE string.
549 */
550 DWORD WINAPI CaptureStringArg(LPCWSTR pSrc, LPWSTR *pDst)
551 {
552 if (pDst == NULL)
553 return ERROR_INVALID_PARAMETER;
554
555 *pDst = DuplicateString(pSrc);
556
557 return ERROR_SUCCESS;
558 }
559
560
561 /**************************************************************************
562 * CaptureAndConvertAnsiArg [SETUPAPI.@]
563 *
564 * Captures an ANSI string and converts it to a UNICODE string.
565 *
566 * PARAMS
567 * lpSrc [I] ANSI string to be captured
568 * lpDst [O] Pointer to the captured UNICODE string
569 *
570 * RETURNS
571 * Success: ERROR_SUCCESS
572 * Failure: ERROR_INVALID_PARAMETER
573 *
574 * NOTE
575 * Call MyFree to release the captured UNICODE string.
576 */
577 DWORD WINAPI CaptureAndConvertAnsiArg(LPCSTR pSrc, LPWSTR *pDst)
578 {
579 if (pDst == NULL)
580 return ERROR_INVALID_PARAMETER;
581
582 *pDst = MultiByteToUnicode(pSrc, CP_ACP);
583
584 return ERROR_SUCCESS;
585 }