winapi_check: We no longer have dlls in nested sub-directories.
[wine/wine-gecko.git] / dlls / setupapi / misc.c
blob0e9dbd11b6087f7ced0d8af9a3efaee938a5eb47
1 /*
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
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "winreg.h"
28 #include "setupapi.h"
30 #include "wine/unicode.h"
31 #include "wine/debug.h"
33 #include "setupapi_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
39 /**************************************************************************
40 * MyFree [SETUPAPI.@]
42 * Frees an allocated memory block from the process heap.
44 * PARAMS
45 * lpMem [I] pointer to memory block which will be freed
47 * RETURNS
48 * None
50 VOID WINAPI MyFree(LPVOID lpMem)
52 TRACE("%p\n", lpMem);
53 HeapFree(GetProcessHeap(), 0, lpMem);
57 /**************************************************************************
58 * MyMalloc [SETUPAPI.@]
60 * Allocates memory block from the process heap.
62 * PARAMS
63 * dwSize [I] size of the allocated memory block
65 * RETURNS
66 * Success: pointer to allocated memory block
67 * Failure: NULL
69 LPVOID WINAPI MyMalloc(DWORD dwSize)
71 TRACE("%u\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.
82 * PARAMS
83 * lpSrc [I] pointer to memory block which will be resized
84 * dwSize [I] new size of the memory block
86 * RETURNS
87 * Success: pointer to the resized memory block
88 * Failure: NULL
90 * NOTES
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 %u\n", lpSrc, dwSize);
98 if (lpSrc == NULL)
99 return HeapAlloc(GetProcessHeap(), 0, dwSize);
101 return HeapReAlloc(GetProcessHeap(), 0, lpSrc, dwSize);
105 /**************************************************************************
106 * DuplicateString [SETUPAPI.@]
108 * Duplicates a unicode string.
110 * PARAMS
111 * lpSrc [I] pointer to the unicode string that will be duplicated
113 * RETURNS
114 * Success: pointer to the duplicated unicode string
115 * Failure: NULL
117 * NOTES
118 * Call MyFree() to release the duplicated string.
120 LPWSTR WINAPI DuplicateString(LPCWSTR lpSrc)
122 LPWSTR lpDst;
124 TRACE("%s\n", debugstr_w(lpSrc));
126 lpDst = MyMalloc((lstrlenW(lpSrc) + 1) * sizeof(WCHAR));
127 if (lpDst == NULL)
128 return NULL;
130 strcpyW(lpDst, lpSrc);
132 return lpDst;
136 /**************************************************************************
137 * QueryRegistryValue [SETUPAPI.@]
139 * Retrieves value data from the registry and allocates memory for the
140 * value data.
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
149 * RETURNS
150 * Success: ERROR_SUCCESS
151 * Failure: Otherwise
153 * NOTES
154 * Use MyFree to release the lpData buffer.
156 LONG WINAPI QueryRegistryValue(HKEY hKey,
157 LPCWSTR lpValueName,
158 LPBYTE *lpData,
159 LPDWORD lpType,
160 LPDWORD lpcbData)
162 LONG lError;
164 TRACE("%p %s %p %p %p\n",
165 hKey, debugstr_w(lpValueName), lpData, lpType, lpcbData);
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;
173 /* Allocate buffer */
174 *lpData = MyMalloc(*lpcbData);
175 if (*lpData == NULL)
176 return ERROR_NOT_ENOUGH_MEMORY;
178 /* Query registry value */
179 lError = RegQueryValueExW(hKey, lpValueName, 0, lpType, *lpData, lpcbData);
180 if (lError != ERROR_SUCCESS)
181 MyFree(*lpData);
183 return lError;
187 /**************************************************************************
188 * IsUserAdmin [SETUPAPI.@]
190 * Checks whether the current user is a member of the Administrators group.
192 * PARAMS
193 * None
195 * RETURNS
196 * Success: TRUE
197 * Failure: FALSE
199 BOOL WINAPI IsUserAdmin(VOID)
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;
209 TRACE("\n");
211 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
213 return FALSE;
216 if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize))
218 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
220 CloseHandle(hToken);
221 return FALSE;
225 lpGroups = MyMalloc(dwSize);
226 if (lpGroups == NULL)
228 CloseHandle(hToken);
229 return FALSE;
232 if (!GetTokenInformation(hToken, TokenGroups, lpGroups, dwSize, &dwSize))
234 MyFree(lpGroups);
235 CloseHandle(hToken);
236 return FALSE;
239 CloseHandle(hToken);
241 if (!AllocateAndInitializeSid(&Authority, 2, SECURITY_BUILTIN_DOMAIN_RID,
242 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
243 &lpSid))
245 MyFree(lpGroups);
246 return FALSE;
249 for (i = 0; i < lpGroups->GroupCount; i++)
251 if (EqualSid(lpSid, lpGroups->Groups[i].Sid))
253 bResult = TRUE;
254 break;
258 FreeSid(lpSid);
259 MyFree(lpGroups);
261 return bResult;
265 /**************************************************************************
266 * MultiByteToUnicode [SETUPAPI.@]
268 * Converts a multi-byte string to a Unicode string.
270 * PARAMS
271 * lpMultiByteStr [I] Multi-byte string to be converted
272 * uCodePage [I] Code page
274 * RETURNS
275 * Success: pointer to the converted Unicode string
276 * Failure: NULL
278 * NOTE
279 * Use MyFree to release the returned Unicode string.
281 LPWSTR WINAPI MultiByteToUnicode(LPCSTR lpMultiByteStr, UINT uCodePage)
283 LPWSTR lpUnicodeStr;
284 int nLength;
286 TRACE("%s %d\n", debugstr_a(lpMultiByteStr), uCodePage);
288 nLength = MultiByteToWideChar(uCodePage, 0, lpMultiByteStr,
289 -1, NULL, 0);
290 if (nLength == 0)
291 return NULL;
293 lpUnicodeStr = MyMalloc(nLength * sizeof(WCHAR));
294 if (lpUnicodeStr == NULL)
295 return NULL;
297 if (!MultiByteToWideChar(uCodePage, 0, lpMultiByteStr,
298 nLength, lpUnicodeStr, nLength))
300 MyFree(lpUnicodeStr);
301 return NULL;
304 return lpUnicodeStr;
308 /**************************************************************************
309 * UnicodeToMultiByte [SETUPAPI.@]
311 * Converts a Unicode string to a multi-byte string.
313 * PARAMS
314 * lpUnicodeStr [I] Unicode string to be converted
315 * uCodePage [I] Code page
317 * RETURNS
318 * Success: pointer to the converted multi-byte string
319 * Failure: NULL
321 * NOTE
322 * Use MyFree to release the returned multi-byte string.
324 LPSTR WINAPI UnicodeToMultiByte(LPCWSTR lpUnicodeStr, UINT uCodePage)
326 LPSTR lpMultiByteStr;
327 int nLength;
329 TRACE("%s %d\n", debugstr_w(lpUnicodeStr), uCodePage);
331 nLength = WideCharToMultiByte(uCodePage, 0, lpUnicodeStr, -1,
332 NULL, 0, NULL, NULL);
333 if (nLength == 0)
334 return NULL;
336 lpMultiByteStr = MyMalloc(nLength);
337 if (lpMultiByteStr == NULL)
338 return NULL;
340 if (!WideCharToMultiByte(uCodePage, 0, lpUnicodeStr, -1,
341 lpMultiByteStr, nLength, NULL, NULL))
343 MyFree(lpMultiByteStr);
344 return NULL;
347 return lpMultiByteStr;
351 /**************************************************************************
352 * DoesUserHavePrivilege [SETUPAPI.@]
354 * Check whether the current user has got a given privilege.
356 * PARAMS
357 * lpPrivilegeName [I] Name of the privilege to be checked
359 * RETURNS
360 * Success: TRUE
361 * Failure: FALSE
363 BOOL WINAPI DoesUserHavePrivilege(LPCWSTR lpPrivilegeName)
365 HANDLE hToken;
366 DWORD dwSize;
367 PTOKEN_PRIVILEGES lpPrivileges;
368 LUID PrivilegeLuid;
369 DWORD i;
370 BOOL bResult = FALSE;
372 TRACE("%s\n", debugstr_w(lpPrivilegeName));
374 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
375 return FALSE;
377 if (!GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwSize))
379 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
381 CloseHandle(hToken);
382 return FALSE;
386 lpPrivileges = MyMalloc(dwSize);
387 if (lpPrivileges == NULL)
389 CloseHandle(hToken);
390 return FALSE;
393 if (!GetTokenInformation(hToken, TokenPrivileges, lpPrivileges, dwSize, &dwSize))
395 MyFree(lpPrivileges);
396 CloseHandle(hToken);
397 return FALSE;
400 CloseHandle(hToken);
402 if (!LookupPrivilegeValueW(NULL, lpPrivilegeName, &PrivilegeLuid))
404 MyFree(lpPrivileges);
405 return FALSE;
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)
413 bResult = TRUE;
417 MyFree(lpPrivileges);
419 return bResult;
423 /**************************************************************************
424 * EnablePrivilege [SETUPAPI.@]
426 * Enables or disables one of the current users privileges.
428 * PARAMS
429 * lpPrivilegeName [I] Name of the privilege to be changed
430 * bEnable [I] TRUE: Enables the privilege
431 * FALSE: Disables the privilege
433 * RETURNS
434 * Success: TRUE
435 * Failure: FALSE
437 BOOL WINAPI EnablePrivilege(LPCWSTR lpPrivilegeName, BOOL bEnable)
439 TOKEN_PRIVILEGES Privileges;
440 HANDLE hToken;
441 BOOL bResult;
443 TRACE("%s %s\n", debugstr_w(lpPrivilegeName), bEnable ? "TRUE" : "FALSE");
445 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
446 return FALSE;
448 Privileges.PrivilegeCount = 1;
449 Privileges.Privileges[0].Attributes = (bEnable) ? SE_PRIVILEGE_ENABLED : 0;
451 if (!LookupPrivilegeValueW(NULL, lpPrivilegeName,
452 &Privileges.Privileges[0].Luid))
454 CloseHandle(hToken);
455 return FALSE;
458 bResult = AdjustTokenPrivileges(hToken, FALSE, &Privileges, 0, NULL, NULL);
460 CloseHandle(hToken);
462 return bResult;
466 /**************************************************************************
467 * DelayedMove [SETUPAPI.@]
469 * Moves a file upon the next reboot.
471 * PARAMS
472 * lpExistingFileName [I] Current file name
473 * lpNewFileName [I] New file name
475 * RETURNS
476 * Success: TRUE
477 * Failure: FALSE
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.
491 * PARAMS
492 * lpFileName [I] Name of the file to check
493 * lpNewFileName [O] Optional information about the existing file
495 * RETURNS
496 * Success: TRUE
497 * Failure: FALSE
499 BOOL WINAPI FileExists(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFileFindData)
501 WIN32_FIND_DATAW FindData;
502 HANDLE hFind;
503 UINT uErrorMode;
504 DWORD dwError;
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);
514 return FALSE;
517 FindClose(hFind);
519 if (lpFileFindData)
520 memcpy(lpFileFindData, &FindData, sizeof(WIN32_FIND_DATAW));
522 SetErrorMode(uErrorMode);
524 return TRUE;
528 /**************************************************************************
529 * CaptureStringArg [SETUPAPI.@]
531 * Captures a UNICODE string.
533 * PARAMS
534 * lpSrc [I] UNICODE string to be captured
535 * lpDst [O] Pointer to the captured UNICODE string
537 * RETURNS
538 * Success: ERROR_SUCCESS
539 * Failure: ERROR_INVALID_PARAMETER
541 * NOTE
542 * Call MyFree to release the captured UNICODE string.
544 DWORD WINAPI CaptureStringArg(LPCWSTR pSrc, LPWSTR *pDst)
546 if (pDst == NULL)
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.
560 * PARAMS
561 * lpSrc [I] ANSI string to be captured
562 * lpDst [O] Pointer to the captured UNICODE string
564 * RETURNS
565 * Success: ERROR_SUCCESS
566 * Failure: ERROR_INVALID_PARAMETER
568 * NOTE
569 * Call MyFree to release the captured UNICODE string.
571 DWORD WINAPI CaptureAndConvertAnsiArg(LPCSTR pSrc, LPWSTR *pDst)
573 if (pDst == NULL)
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.
587 * PARAMS
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
594 * RETURNS
595 * Success: ERROR_SUCCESS
596 * Failure: Other
598 * NOTE
599 * Call UnmapAndCloseFile to release the file.
601 DWORD WINAPI OpenAndMapFileForRead(LPCWSTR lpFileName,
602 LPDWORD lpSize,
603 LPHANDLE lpFile,
604 LPHANDLE lpMapping,
605 LPVOID *lpBuffer)
607 DWORD dwError;
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);
622 return dwError;
625 *lpMapping = CreateFileMappingW(*lpFile, NULL, PAGE_READONLY, 0,
626 *lpSize, NULL);
627 if (*lpMapping == NULL)
629 dwError = GetLastError();
630 CloseHandle(*lpFile);
631 return dwError;
634 *lpBuffer = MapViewOfFile(*lpMapping, FILE_MAP_READ, 0, 0, *lpSize);
635 if (*lpBuffer == NULL)
637 dwError = GetLastError();
638 CloseHandle(*lpMapping);
639 CloseHandle(*lpFile);
640 return dwError;
643 return ERROR_SUCCESS;
647 /**************************************************************************
648 * UnmapAndCloseFile [SETUPAPI.@]
650 * Unmap and close a mapped file.
652 * PARAMS
653 * hFile [I] Handle to the file
654 * hMapping [I] Handle to the file mapping
655 * lpBuffer [I] Pointer to the file buffer
657 * RETURNS
658 * Success: TRUE
659 * Failure: FALSE
661 BOOL WINAPI UnmapAndCloseFile(HANDLE hFile, HANDLE hMapping, LPVOID lpBuffer)
663 TRACE("%p %p %p\n",
664 hFile, hMapping, lpBuffer);
666 if (!UnmapViewOfFile(lpBuffer))
667 return FALSE;
669 if (!CloseHandle(hMapping))
670 return FALSE;
672 if (!CloseHandle(hFile))
673 return FALSE;
675 return TRUE;
679 /**************************************************************************
680 * StampFileSecurity [SETUPAPI.@]
682 * Assign a new security descriptor to the given file.
684 * PARAMS
685 * lpFileName [I] Name of the file
686 * pSecurityDescriptor [I] New security descriptor
688 * RETURNS
689 * Success: ERROR_SUCCESS
690 * Failure: other
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.
710 * PARAMS
711 * lpFileName [I] Name of the file
713 * RETURNS
714 * Success: ERROR_SUCCESS
715 * Failure: other
717 DWORD WINAPI TakeOwnershipOfFile(LPCWSTR lpFileName)
719 SECURITY_DESCRIPTOR SecDesc;
720 HANDLE hToken = NULL;
721 PTOKEN_OWNER pOwner = NULL;
722 DWORD dwError;
723 DWORD dwSize;
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))
732 goto fail;
735 pOwner = (PTOKEN_OWNER)MyMalloc(dwSize);
736 if (pOwner == NULL)
738 CloseHandle(hToken);
739 return ERROR_NOT_ENOUGH_MEMORY;
742 if (!GetTokenInformation(hToken, TokenOwner, pOwner, dwSize, &dwSize))
744 goto fail;
747 if (!InitializeSecurityDescriptor(&SecDesc, SECURITY_DESCRIPTOR_REVISION))
749 goto fail;
752 if (!SetSecurityDescriptorOwner(&SecDesc, pOwner->Owner, FALSE))
754 goto fail;
757 if (!SetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION, &SecDesc))
759 goto fail;
762 MyFree(pOwner);
763 CloseHandle(hToken);
765 return ERROR_SUCCESS;
767 fail:;
768 dwError = GetLastError();
770 MyFree(pOwner);
772 if (hToken != NULL)
773 CloseHandle(hToken);
775 return dwError;
779 /**************************************************************************
780 * RetreiveFileSecurity [SETUPAPI.@]
782 * Retrieve the security descriptor that is associated with the given file.
784 * PARAMS
785 * lpFileName [I] Name of the file
787 * RETURNS
788 * Success: ERROR_SUCCESS
789 * Failure: other
791 DWORD WINAPI RetreiveFileSecurity(LPCWSTR lpFileName,
792 PSECURITY_DESCRIPTOR *pSecurityDescriptor)
794 PSECURITY_DESCRIPTOR SecDesc;
795 DWORD dwSize = 0x100;
796 DWORD dwError;
798 SecDesc = (PSECURITY_DESCRIPTOR)MyMalloc(dwSize);
799 if (SecDesc == NULL)
800 return ERROR_NOT_ENOUGH_MEMORY;
802 if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION |
803 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
804 SecDesc, dwSize, &dwSize))
806 *pSecurityDescriptor = SecDesc;
807 return ERROR_SUCCESS;
810 dwError = GetLastError();
811 if (dwError != ERROR_INSUFFICIENT_BUFFER)
813 MyFree(SecDesc);
814 return dwError;
817 SecDesc = (PSECURITY_DESCRIPTOR)MyRealloc(SecDesc, dwSize);
818 if (SecDesc == NULL)
819 return ERROR_NOT_ENOUGH_MEMORY;
821 if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION |
822 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
823 SecDesc, dwSize, &dwSize))
825 *pSecurityDescriptor = SecDesc;
826 return ERROR_SUCCESS;
829 dwError = GetLastError();
830 MyFree(SecDesc);
832 return dwError;
836 static DWORD global_flags = 0; /* FIXME: what should be in here? */
838 /***********************************************************************
839 * pSetupGetGlobalFlags (SETUPAPI.@)
841 DWORD WINAPI pSetupGetGlobalFlags(void)
843 FIXME( "stub\n" );
844 return global_flags;
848 /***********************************************************************
849 * pSetupSetGlobalFlags (SETUPAPI.@)
851 void WINAPI pSetupSetGlobalFlags( DWORD flags )
853 global_flags = flags;
856 /***********************************************************************
857 * CMP_WaitNoPendingInstallEvents (SETUPAPI.@)
859 DWORD WINAPI CMP_WaitNoPendingInstallEvents( DWORD dwTimeout )
861 FIXME("%d\n", dwTimeout);
862 return WAIT_OBJECT_0;
865 /***********************************************************************
866 * AssertFail (SETUPAPI.@)
868 * Shows an assert fail error messagebox
870 * PARAMS
871 * lpFile [I] file where assert failed
872 * uLine [I] line number in file
873 * lpMessage [I] assert message
876 void WINAPI AssertFail(LPCSTR lpFile, UINT uLine, LPCSTR lpMessage)
878 FIXME("%s %u %s\n", lpFile, uLine, lpMessage);
881 /***********************************************************************
882 * SetupCopyOEMInfA (SETUPAPI.@)
884 BOOL WINAPI SetupCopyOEMInfA( PCSTR source, PCSTR location,
885 DWORD media_type, DWORD style, PSTR dest,
886 DWORD buffer_size, PDWORD required_size, PSTR *component )
888 BOOL ret = FALSE;
889 WCHAR destW[MAX_PATH], *sourceW = NULL, *locationW = NULL;
890 INT size = sizeof(destW);
892 TRACE("%s, %s, %d, %d, %p, %d, %p, %p\n", debugstr_a(source), debugstr_a(location),
893 media_type, style, dest, buffer_size, required_size, component);
895 if (source && !(sourceW = strdupAtoW( source ))) return FALSE;
896 if (location && !(locationW = strdupAtoW( location ))) goto done;
898 if (!(ret = SetupCopyOEMInfW( sourceW, locationW, media_type, style, destW, size, NULL, NULL )))
899 goto done;
901 size = WideCharToMultiByte( CP_ACP, 0, destW, -1, NULL, 0, NULL, NULL );
902 if (required_size) *required_size = size;
904 if (dest)
906 if (buffer_size >= size)
908 WideCharToMultiByte( CP_ACP, 0, destW, -1, dest, buffer_size, NULL, NULL );
909 if (component) *component = strrchr( dest, '\\' ) + 1;
911 else
913 SetLastError( ERROR_INSUFFICIENT_BUFFER );
914 goto done;
918 done:
919 HeapFree( GetProcessHeap(), 0, sourceW );
920 HeapFree( GetProcessHeap(), 0, locationW );
921 return ret;
924 /***********************************************************************
925 * SetupCopyOEMInfW (SETUPAPI.@)
927 BOOL WINAPI SetupCopyOEMInfW( PCWSTR source, PCWSTR location,
928 DWORD media_type, DWORD style, PWSTR dest,
929 DWORD buffer_size, PDWORD required_size, PWSTR *component )
931 BOOL ret = FALSE;
932 WCHAR target[MAX_PATH], *p;
933 static const WCHAR inf_oem[] = { '\\','i','n','f','\\','O','E','M',0 };
934 DWORD size;
936 TRACE("%s, %s, %d, %d, %p, %d, %p, %p\n", debugstr_w(source), debugstr_w(location),
937 media_type, style, dest, buffer_size, required_size, component);
939 if (!GetWindowsDirectoryW( target, sizeof(target)/sizeof(WCHAR) )) return FALSE;
941 strcatW( target, inf_oem );
942 p = strrchrW( source, '\\' ) + 1;
943 strcatW( target, p );
945 size = strlenW( target ) + 1;
946 if (dest)
948 if (buffer_size >= size)
950 /* FIXME: honour style flags */
951 if ((ret = CopyFileW( source, target, FALSE )))
953 if (style & SP_COPY_DELETESOURCE) DeleteFileW( source );
954 strcpyW( dest, target );
957 else
959 SetLastError( ERROR_INSUFFICIENT_BUFFER );
960 ret = FALSE;
964 if (component) *component = p;
965 if (required_size) *required_size = size;
967 return ret;