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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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();
837 static DWORD global_flags = 0; /* FIXME: what should be in here? */
839 /***********************************************************************
840 * pSetupGetGlobalFlags (SETUPAPI.@)
842 DWORD WINAPI pSetupGetGlobalFlags(void)
849 /***********************************************************************
850 * pSetupSetGlobalFlags (SETUPAPI.@)
852 void WINAPI pSetupSetGlobalFlags( DWORD flags )
854 global_flags = flags;
857 /***********************************************************************
858 * CMP_WaitNoPendingInstallEvents (SETUPAPI.@)
860 DWORD WINAPI CMP_WaitNoPendingInstallEvents( DWORD dwTimeout )
862 FIXME("%ld\n", dwTimeout);
863 return WAIT_OBJECT_0;