2 * Setupapi miscellaneous functions
4 * Copyright 2005 Eric Kohl
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.
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.
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
30 #include "wine/unicode.h"
31 #include "wine/debug.h"
33 #include "setupapi_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
39 /**************************************************************************
42 * Frees an allocated memory block from the process heap.
45 * lpMem [I] pointer to memory block which will be freed
50 VOID WINAPI
MyFree(LPVOID lpMem
)
53 HeapFree(GetProcessHeap(), 0, lpMem
);
57 /**************************************************************************
58 * MyMalloc [SETUPAPI.@]
60 * Allocates memory block from the process heap.
63 * dwSize [I] size of the allocated memory block
66 * Success: pointer to allocated memory block
69 LPVOID WINAPI
MyMalloc(DWORD dwSize
)
71 TRACE("%lu\n", dwSize
);
72 return HeapAlloc(GetProcessHeap(), 0, dwSize
);
76 /**************************************************************************
77 * MyRealloc [SETUPAPI.@]
79 * Changes the size of an allocated memory block or allocates a memory
80 * block from the process heap.
83 * lpSrc [I] pointer to memory block which will be resized
84 * dwSize [I] new size of the memory block
87 * Success: pointer to the resized memory block
91 * If lpSrc is a NULL-pointer, then MyRealloc allocates a memory
92 * block like MyMalloc.
94 LPVOID WINAPI
MyRealloc(LPVOID lpSrc
, DWORD dwSize
)
96 TRACE("%p %lu\n", lpSrc
, dwSize
);
99 return HeapAlloc(GetProcessHeap(), 0, dwSize
);
101 return HeapReAlloc(GetProcessHeap(), 0, lpSrc
, dwSize
);
105 /**************************************************************************
106 * DuplicateString [SETUPAPI.@]
108 * Duplicates a unicode string.
111 * lpSrc [I] pointer to the unicode string that will be duplicated
114 * Success: pointer to the duplicated unicode string
118 * Call MyFree() to release the duplicated string.
120 LPWSTR WINAPI
DuplicateString(LPCWSTR lpSrc
)
124 TRACE("%s\n", debugstr_w(lpSrc
));
126 lpDst
= MyMalloc((lstrlenW(lpSrc
) + 1) * sizeof(WCHAR
));
130 strcpyW(lpDst
, lpSrc
);
136 /**************************************************************************
137 * QueryRegistryValue [SETUPAPI.@]
139 * Retrieves value data from the registry and allocates memory for the
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
150 * Success: ERROR_SUCCESS
154 * Use MyFree to release the lpData buffer.
156 LONG WINAPI
QueryRegistryValue(HKEY hKey
,
164 TRACE("%p %s %p %p %p\n",
165 hKey
, debugstr_w(lpValueName
), lpData
, lpType
, lpcbData
);
167 /* Get required buffer size */
169 lError
= RegQueryValueExW(hKey
, lpValueName
, 0, lpType
, NULL
, lpcbData
);
170 if (lError
!= ERROR_SUCCESS
)
173 /* Allocate buffer */
174 *lpData
= MyMalloc(*lpcbData
);
176 return ERROR_NOT_ENOUGH_MEMORY
;
178 /* Query registry value */
179 lError
= RegQueryValueExW(hKey
, lpValueName
, 0, lpType
, *lpData
, lpcbData
);
180 if (lError
!= ERROR_SUCCESS
)
187 /**************************************************************************
188 * IsUserAdmin [SETUPAPI.@]
190 * Checks whether the current user is a member of the Administrators group.
199 BOOL WINAPI
IsUserAdmin(VOID
)
201 SID_IDENTIFIER_AUTHORITY Authority
= {SECURITY_NT_AUTHORITY
};
204 PTOKEN_GROUPS lpGroups
;
207 BOOL bResult
= FALSE
;
211 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
216 if (!GetTokenInformation(hToken
, TokenGroups
, NULL
, 0, &dwSize
))
218 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
225 lpGroups
= MyMalloc(dwSize
);
226 if (lpGroups
== NULL
)
232 if (!GetTokenInformation(hToken
, TokenGroups
, lpGroups
, dwSize
, &dwSize
))
241 if (!AllocateAndInitializeSid(&Authority
, 2, SECURITY_BUILTIN_DOMAIN_RID
,
242 DOMAIN_ALIAS_RID_ADMINS
, 0, 0, 0, 0, 0, 0,
249 for (i
= 0; i
< lpGroups
->GroupCount
; i
++)
251 if (EqualSid(lpSid
, &lpGroups
->Groups
[i
].Sid
))
265 /**************************************************************************
266 * MultiByteToUnicode [SETUPAPI.@]
268 * Converts a multi-byte string to a Unicode string.
271 * lpMultiByteStr [I] Multi-byte string to be converted
272 * uCodePage [I] Code page
275 * Success: pointer to the converted Unicode string
279 * Use MyFree to release the returned Unicode string.
281 LPWSTR WINAPI
MultiByteToUnicode(LPCSTR lpMultiByteStr
, UINT uCodePage
)
286 TRACE("%s %d\n", debugstr_a(lpMultiByteStr
), uCodePage
);
288 nLength
= MultiByteToWideChar(uCodePage
, 0, lpMultiByteStr
,
293 lpUnicodeStr
= MyMalloc(nLength
* sizeof(WCHAR
));
294 if (lpUnicodeStr
== NULL
)
297 if (!MultiByteToWideChar(uCodePage
, 0, lpMultiByteStr
,
298 nLength
, lpUnicodeStr
, nLength
))
300 MyFree(lpUnicodeStr
);
308 /**************************************************************************
309 * UnicodeToMultiByte [SETUPAPI.@]
311 * Converts a Unicode string to a multi-byte string.
314 * lpUnicodeStr [I] Unicode string to be converted
315 * uCodePage [I] Code page
318 * Success: pointer to the converted multi-byte string
322 * Use MyFree to release the returned multi-byte string.
324 LPSTR WINAPI
UnicodeToMultiByte(LPCWSTR lpUnicodeStr
, UINT uCodePage
)
326 LPSTR lpMultiByteStr
;
329 TRACE("%s %d\n", debugstr_w(lpUnicodeStr
), uCodePage
);
331 nLength
= WideCharToMultiByte(uCodePage
, 0, lpUnicodeStr
, -1,
332 NULL
, 0, NULL
, NULL
);
336 lpMultiByteStr
= MyMalloc(nLength
);
337 if (lpMultiByteStr
== NULL
)
340 if (!WideCharToMultiByte(uCodePage
, 0, lpUnicodeStr
, -1,
341 lpMultiByteStr
, nLength
, NULL
, NULL
))
343 MyFree(lpMultiByteStr
);
347 return lpMultiByteStr
;
351 /**************************************************************************
352 * DoesUserHavePrivilege [SETUPAPI.@]
354 * Check whether the current user has got a given privilege.
357 * lpPrivilegeName [I] Name of the privilege to be checked
363 BOOL WINAPI
DoesUserHavePrivilege(LPCWSTR lpPrivilegeName
)
367 PTOKEN_PRIVILEGES lpPrivileges
;
370 BOOL bResult
= FALSE
;
372 TRACE("%s\n", debugstr_w(lpPrivilegeName
));
374 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
377 if (!GetTokenInformation(hToken
, TokenPrivileges
, NULL
, 0, &dwSize
))
379 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
386 lpPrivileges
= MyMalloc(dwSize
);
387 if (lpPrivileges
== NULL
)
393 if (!GetTokenInformation(hToken
, TokenPrivileges
, lpPrivileges
, dwSize
, &dwSize
))
395 MyFree(lpPrivileges
);
402 if (!LookupPrivilegeValueW(NULL
, lpPrivilegeName
, &PrivilegeLuid
))
404 MyFree(lpPrivileges
);
408 for (i
= 0; i
< lpPrivileges
->PrivilegeCount
; i
++)
410 if (lpPrivileges
->Privileges
[i
].Luid
.HighPart
== PrivilegeLuid
.HighPart
&&
411 lpPrivileges
->Privileges
[i
].Luid
.LowPart
== PrivilegeLuid
.LowPart
)
417 MyFree(lpPrivileges
);
423 /**************************************************************************
424 * EnablePrivilege [SETUPAPI.@]
426 * Enables or disables one of the current users privileges.
429 * lpPrivilegeName [I] Name of the privilege to be changed
430 * bEnable [I] TRUE: Enables the privilege
431 * FALSE: Disables the privilege
437 BOOL WINAPI
EnablePrivilege(LPCWSTR lpPrivilegeName
, BOOL bEnable
)
439 TOKEN_PRIVILEGES Privileges
;
443 TRACE("%s %s\n", debugstr_w(lpPrivilegeName
), bEnable
? "TRUE" : "FALSE");
445 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
448 Privileges
.PrivilegeCount
= 1;
449 Privileges
.Privileges
[0].Attributes
= (bEnable
) ? SE_PRIVILEGE_ENABLED
: 0;
451 if (!LookupPrivilegeValueW(NULL
, lpPrivilegeName
,
452 &Privileges
.Privileges
[0].Luid
))
458 bResult
= AdjustTokenPrivileges(hToken
, FALSE
, &Privileges
, 0, NULL
, NULL
);
466 /**************************************************************************
467 * DelayedMove [SETUPAPI.@]
469 * Moves a file upon the next reboot.
472 * lpExistingFileName [I] Current file name
473 * lpNewFileName [I] New file name
479 BOOL WINAPI
DelayedMove(LPCWSTR lpExistingFileName
, LPCWSTR lpNewFileName
)
481 return MoveFileExW(lpExistingFileName
, lpNewFileName
,
482 MOVEFILE_REPLACE_EXISTING
| MOVEFILE_DELAY_UNTIL_REBOOT
);
486 /**************************************************************************
487 * FileExists [SETUPAPI.@]
489 * Checks whether a file exists.
492 * lpFileName [I] Name of the file to check
493 * lpNewFileName [O] Optional information about the existing file
499 BOOL WINAPI
FileExists(LPCWSTR lpFileName
, LPWIN32_FIND_DATAW lpFileFindData
)
501 WIN32_FIND_DATAW FindData
;
506 uErrorMode
= SetErrorMode(SEM_FAILCRITICALERRORS
);
508 hFind
= FindFirstFileW(lpFileName
, &FindData
);
509 if (hFind
== INVALID_HANDLE_VALUE
)
511 dwError
= GetLastError();
512 SetErrorMode(uErrorMode
);
513 SetLastError(dwError
);
520 memcpy(lpFileFindData
, &FindData
, sizeof(WIN32_FIND_DATAW
));
522 SetErrorMode(uErrorMode
);
528 /**************************************************************************
529 * CaptureStringArg [SETUPAPI.@]
531 * Captures a UNICODE string.
534 * lpSrc [I] UNICODE string to be captured
535 * lpDst [O] Pointer to the captured UNICODE string
538 * Success: ERROR_SUCCESS
539 * Failure: ERROR_INVALID_PARAMETER
542 * Call MyFree to release the captured UNICODE string.
544 DWORD WINAPI
CaptureStringArg(LPCWSTR pSrc
, LPWSTR
*pDst
)
547 return ERROR_INVALID_PARAMETER
;
549 *pDst
= DuplicateString(pSrc
);
551 return ERROR_SUCCESS
;
555 /**************************************************************************
556 * CaptureAndConvertAnsiArg [SETUPAPI.@]
558 * Captures an ANSI string and converts it to a UNICODE string.
561 * lpSrc [I] ANSI string to be captured
562 * lpDst [O] Pointer to the captured UNICODE string
565 * Success: ERROR_SUCCESS
566 * Failure: ERROR_INVALID_PARAMETER
569 * Call MyFree to release the captured UNICODE string.
571 DWORD WINAPI
CaptureAndConvertAnsiArg(LPCSTR pSrc
, LPWSTR
*pDst
)
574 return ERROR_INVALID_PARAMETER
;
576 *pDst
= MultiByteToUnicode(pSrc
, CP_ACP
);
578 return ERROR_SUCCESS
;
582 /**************************************************************************
583 * OpenAndMapFileForRead [SETUPAPI.@]
585 * Open and map a file to a buffer.
588 * lpFileName [I] Name of the file to be opened
589 * lpSize [O] Pointer to the file size
590 * lpFile [0] Pointer to the file handle
591 * lpMapping [0] Pointer to the mapping handle
592 * lpBuffer [0] Pointer to the file buffer
595 * Success: ERROR_SUCCESS
599 * Call UnmapAndCloseFile to release the file.
601 DWORD WINAPI
OpenAndMapFileForRead(LPCWSTR lpFileName
,
609 TRACE("%s %p %p %p %p\n",
610 debugstr_w(lpFileName
), lpSize
, lpFile
, lpMapping
, lpBuffer
);
612 *lpFile
= CreateFileW(lpFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
613 OPEN_EXISTING
, 0, NULL
);
614 if (*lpFile
== INVALID_HANDLE_VALUE
)
615 return GetLastError();
617 *lpSize
= GetFileSize(*lpFile
, NULL
);
618 if (*lpSize
== INVALID_FILE_SIZE
)
620 dwError
= GetLastError();
621 CloseHandle(*lpFile
);
625 *lpMapping
= CreateFileMappingW(*lpFile
, NULL
, PAGE_READONLY
, 0,
627 if (*lpMapping
== NULL
)
629 dwError
= GetLastError();
630 CloseHandle(*lpFile
);
634 *lpBuffer
= MapViewOfFile(*lpMapping
, FILE_MAP_READ
, 0, 0, *lpSize
);
635 if (*lpBuffer
== NULL
)
637 dwError
= GetLastError();
638 CloseHandle(*lpMapping
);
639 CloseHandle(*lpFile
);
643 return ERROR_SUCCESS
;
647 /**************************************************************************
648 * UnmapAndCloseFile [SETUPAPI.@]
650 * Unmap and close a mapped file.
653 * hFile [I] Handle to the file
654 * hMapping [I] Handle to the file mapping
655 * lpBuffer [I] Pointer to the file buffer
661 BOOL WINAPI
UnmapAndCloseFile(HANDLE hFile
, HANDLE hMapping
, LPVOID lpBuffer
)
664 hFile
, hMapping
, lpBuffer
);
666 if (!UnmapViewOfFile(lpBuffer
))
669 if (!CloseHandle(hMapping
))
672 if (!CloseHandle(hFile
))
679 /**************************************************************************
680 * StampFileSecurity [SETUPAPI.@]
682 * Assign a new security descriptor to the given file.
685 * lpFileName [I] Name of the file
686 * pSecurityDescriptor [I] New security descriptor
689 * Success: ERROR_SUCCESS
692 DWORD WINAPI
StampFileSecurity(LPCWSTR lpFileName
, PSECURITY_DESCRIPTOR pSecurityDescriptor
)
694 TRACE("%s %p\n", debugstr_w(lpFileName
), pSecurityDescriptor
);
696 if (!SetFileSecurityW(lpFileName
, OWNER_SECURITY_INFORMATION
|
697 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
698 pSecurityDescriptor
))
699 return GetLastError();
701 return ERROR_SUCCESS
;
705 /**************************************************************************
706 * TakeOwnershipOfFile [SETUPAPI.@]
708 * Takes the ownership of the given file.
711 * lpFileName [I] Name of the file
714 * Success: ERROR_SUCCESS
717 DWORD WINAPI
TakeOwnershipOfFile(LPCWSTR lpFileName
)
719 SECURITY_DESCRIPTOR SecDesc
;
720 HANDLE hToken
= NULL
;
721 PTOKEN_OWNER pOwner
= NULL
;
725 TRACE("%s\n", debugstr_w(lpFileName
));
727 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
728 return GetLastError();
730 if (!GetTokenInformation(hToken
, TokenOwner
, NULL
, 0, &dwSize
))
735 pOwner
= (PTOKEN_OWNER
)MyMalloc(dwSize
);
739 return ERROR_NOT_ENOUGH_MEMORY
;
742 if (!GetTokenInformation(hToken
, TokenOwner
, pOwner
, dwSize
, &dwSize
))
747 if (!InitializeSecurityDescriptor(&SecDesc
, SECURITY_DESCRIPTOR_REVISION
))
752 if (!SetSecurityDescriptorOwner(&SecDesc
, pOwner
->Owner
, FALSE
))
757 if (!SetFileSecurityW(lpFileName
, OWNER_SECURITY_INFORMATION
, &SecDesc
))
765 return ERROR_SUCCESS
;
768 dwError
= GetLastError();
780 /**************************************************************************
781 * RetreiveFileSecurity [SETUPAPI.@]
783 * Retrieve the security descriptor that is associated with the given file.
786 * lpFileName [I] Name of the file
789 * Success: ERROR_SUCCESS
792 DWORD WINAPI
RetreiveFileSecurity(LPCWSTR lpFileName
,
793 PSECURITY_DESCRIPTOR
*pSecurityDescriptor
)
795 PSECURITY_DESCRIPTOR SecDesc
;
796 DWORD dwSize
= 0x100;
799 SecDesc
= (PSECURITY_DESCRIPTOR
)MyMalloc(dwSize
);
801 return ERROR_NOT_ENOUGH_MEMORY
;
803 if (GetFileSecurityW(lpFileName
, OWNER_SECURITY_INFORMATION
|
804 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
805 SecDesc
, dwSize
, &dwSize
))
807 *pSecurityDescriptor
= SecDesc
;
808 return ERROR_SUCCESS
;
811 dwError
= GetLastError();
812 if (dwError
!= ERROR_INSUFFICIENT_BUFFER
)
818 SecDesc
= (PSECURITY_DESCRIPTOR
)MyRealloc(SecDesc
, dwSize
);
820 return ERROR_NOT_ENOUGH_MEMORY
;
822 if (GetFileSecurityW(lpFileName
, OWNER_SECURITY_INFORMATION
|
823 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
824 SecDesc
, dwSize
, &dwSize
))
826 *pSecurityDescriptor
= SecDesc
;
827 return ERROR_SUCCESS
;
830 dwError
= GetLastError();