implemented SetupDiSetSelectedDriverA
[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("%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 /**************************************************************************
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 }
586
587
588 /**************************************************************************
589 * OpenAndMapFileForRead [SETUPAPI.@]
590 *
591 * Open and map a file to a buffer.
592 *
593 * PARAMS
594 * lpFileName [I] Name of the file to be opened
595 * lpSize [O] Pointer to the file size
596 * lpFile [0] Pointer to the file handle
597 * lpMapping [0] Pointer to the mapping handle
598 * lpBuffer [0] Pointer to the file buffer
599 *
600 * RETURNS
601 * Success: ERROR_SUCCESS
602 * Failure: Other
603 *
604 * NOTE
605 * Call UnmapAndCloseFile to release the file.
606 */
607 DWORD WINAPI OpenAndMapFileForRead(LPCWSTR lpFileName,
608 LPDWORD lpSize,
609 LPHANDLE lpFile,
610 LPHANDLE lpMapping,
611 LPVOID *lpBuffer)
612 {
613 DWORD dwError;
614
615 TRACE("%s %p %p %p %p\n",
616 debugstr_w(lpFileName), lpSize, lpFile, lpMapping, lpBuffer);
617
618 *lpFile = CreateFileW(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
619 OPEN_EXISTING, 0, NULL);
620 if (*lpFile == INVALID_HANDLE_VALUE)
621 return GetLastError();
622
623 *lpSize = GetFileSize(*lpFile, NULL);
624 if (*lpSize == INVALID_FILE_SIZE)
625 {
626 dwError = GetLastError();
627 CloseHandle(*lpFile);
628 return dwError;
629 }
630
631 *lpMapping = CreateFileMappingW(*lpFile, NULL, PAGE_READONLY, 0,
632 *lpSize, NULL);
633 if (*lpMapping == NULL)
634 {
635 dwError = GetLastError();
636 CloseHandle(*lpFile);
637 return dwError;
638 }
639
640 *lpBuffer = MapViewOfFile(*lpMapping, FILE_MAP_READ, 0, 0, *lpSize);
641 if (*lpBuffer == NULL)
642 {
643 dwError = GetLastError();
644 CloseHandle(*lpMapping);
645 CloseHandle(*lpFile);
646 return dwError;
647 }
648
649 return ERROR_SUCCESS;
650 }
651
652
653 /**************************************************************************
654 * UnmapAndCloseFile [SETUPAPI.@]
655 *
656 * Unmap and close a mapped file.
657 *
658 * PARAMS
659 * hFile [I] Handle to the file
660 * hMapping [I] Handle to the file mapping
661 * lpBuffer [I] Pointer to the file buffer
662 *
663 * RETURNS
664 * Success: TRUE
665 * Failure: FALSE
666 */
667 BOOL WINAPI UnmapAndCloseFile(HANDLE hFile, HANDLE hMapping, LPVOID lpBuffer)
668 {
669 TRACE("%p %p %p\n",
670 hFile, hMapping, lpBuffer);
671
672 if (!UnmapViewOfFile(lpBuffer))
673 return FALSE;
674
675 if (!CloseHandle(hMapping))
676 return FALSE;
677
678 if (!CloseHandle(hFile))
679 return FALSE;
680
681 return TRUE;
682 }
683
684
685 /**************************************************************************
686 * StampFileSecurity [SETUPAPI.@]
687 *
688 * Assign a new security descriptor to the given file.
689 *
690 * PARAMS
691 * lpFileName [I] Name of the file
692 * pSecurityDescriptor [I] New security descriptor
693 *
694 * RETURNS
695 * Success: ERROR_SUCCESS
696 * Failure: other
697 */
698 DWORD WINAPI StampFileSecurity(LPCWSTR lpFileName, PSECURITY_DESCRIPTOR pSecurityDescriptor)
699 {
700 TRACE("%s %p\n", debugstr_w(lpFileName), pSecurityDescriptor);
701
702 if (!SetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION |
703 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
704 pSecurityDescriptor))
705 return GetLastError();
706
707 return ERROR_SUCCESS;
708 }
709
710
711 /**************************************************************************
712 * TakeOwnershipOfFile [SETUPAPI.@]
713 *
714 * Takes the ownership of the given file.
715 *
716 * PARAMS
717 * lpFileName [I] Name of the file
718 *
719 * RETURNS
720 * Success: ERROR_SUCCESS
721 * Failure: other
722 */
723 DWORD WINAPI TakeOwnershipOfFile(LPCWSTR lpFileName)
724 {
725 SECURITY_DESCRIPTOR SecDesc;
726 HANDLE hToken = NULL;
727 PTOKEN_OWNER pOwner = NULL;
728 DWORD dwError;
729 DWORD dwSize;
730
731 TRACE("%s\n", debugstr_w(lpFileName));
732
733 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
734 return GetLastError();
735
736 if (!GetTokenInformation(hToken, TokenOwner, NULL, 0, &dwSize))
737 {
738 goto fail;
739 }
740
741 pOwner = (PTOKEN_OWNER)MyMalloc(dwSize);
742 if (pOwner == NULL)
743 {
744 CloseHandle(hToken);
745 return ERROR_NOT_ENOUGH_MEMORY;
746 }
747
748 if (!GetTokenInformation(hToken, TokenOwner, pOwner, dwSize, &dwSize))
749 {
750 goto fail;
751 }
752
753 if (!InitializeSecurityDescriptor(&SecDesc, SECURITY_DESCRIPTOR_REVISION))
754 {
755 goto fail;
756 }
757
758 if (!SetSecurityDescriptorOwner(&SecDesc, pOwner->Owner, FALSE))
759 {
760 goto fail;
761 }
762
763 if (!SetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION, &SecDesc))
764 {
765 goto fail;
766 }
767
768 MyFree(pOwner);
769 CloseHandle(hToken);
770
771 return ERROR_SUCCESS;
772
773 fail:;
774 dwError = GetLastError();
775
776 if (pOwner != NULL)
777 MyFree(pOwner);
778
779 if (hToken != NULL)
780 CloseHandle(hToken);
781
782 return dwError;
783 }
784
785
786 /**************************************************************************
787 * RetreiveFileSecurity [SETUPAPI.@]
788 *
789 * Retrieve the security descriptor that is associated with the given file.
790 *
791 * PARAMS
792 * lpFileName [I] Name of the file
793 *
794 * RETURNS
795 * Success: ERROR_SUCCESS
796 * Failure: other
797 */
798 DWORD WINAPI RetreiveFileSecurity(LPCWSTR lpFileName,
799 PSECURITY_DESCRIPTOR *pSecurityDescriptor)
800 {
801 PSECURITY_DESCRIPTOR SecDesc;
802 DWORD dwSize = 0x100;
803 DWORD dwError;
804
805 TRACE("%s %p\n", debugstr_w(lpFileName), pSecurityDescriptor);
806
807 SecDesc = (PSECURITY_DESCRIPTOR)MyMalloc(dwSize);
808 if (SecDesc == NULL)
809 return ERROR_NOT_ENOUGH_MEMORY;
810
811 if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION |
812 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
813 SecDesc, dwSize, &dwSize))
814 {
815 *pSecurityDescriptor = SecDesc;
816 return ERROR_SUCCESS;
817 }
818
819 dwError = GetLastError();
820 if (dwError != ERROR_INSUFFICIENT_BUFFER)
821 {
822 MyFree(SecDesc);
823 return dwError;
824 }
825
826 SecDesc = (PSECURITY_DESCRIPTOR)MyRealloc(SecDesc, dwSize);
827 if (SecDesc == NULL)
828 return ERROR_NOT_ENOUGH_MEMORY;
829
830 if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION |
831 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
832 SecDesc, dwSize, &dwSize))
833 {
834 *pSecurityDescriptor = SecDesc;
835 return ERROR_SUCCESS;
836 }
837
838 dwError = GetLastError();
839 MyFree(SecDesc);
840
841 return dwError;
842 }
843
844
845 /**************************************************************************
846 * AssertFail [SETUPAPI.@]
847 *
848 * Display an assertion message.
849 *
850 * PARAMS
851 * lpFile [I] File name
852 * uLine [I] Line number
853 * lpMessage [I] Assertion message
854 *
855 * RETURNS
856 * Nothing
857 */
858 VOID WINAPI AssertFail(LPSTR lpFile, UINT uLine, LPSTR lpMessage)
859 {
860 CHAR szModule[MAX_PATH];
861 CHAR szBuffer[2048];
862 LPSTR lpName;
863 // LPSTR lpBuffer;
864
865 TRACE("%s %u %s\n", lpFile, uLine, lpMessage);
866
867 GetModuleFileNameA(hInstance, szModule, MAX_PATH);
868 lpName = strrchr(szModule, '\\');
869 if (lpName != NULL)
870 lpName++;
871 else
872 lpName = szModule;
873
874 wsprintfA(szBuffer,
875 "Assertion failure at line %u in file %s: %s\n\nCall DebugBreak()?",
876 uLine, lpFile, lpMessage);
877
878 if (MessageBoxA(NULL, szBuffer, lpName, MB_SETFOREGROUND |
879 MB_TASKMODAL | MB_ICONERROR | MB_YESNO) == IDYES)
880 DebugBreak();
881 }
882
883
884 /**************************************************************************
885 * GetSetFileTimestamp [SETUPAPI.@]
886 *
887 * Gets or sets a files timestamp.
888 *
889 * PARAMS
890 * lpFileName [I] File name
891 * lpCreationTime [I/O] Creation time
892 * lpLastAccessTime [I/O] Last access time
893 * lpLastWriteTime [I/O] Last write time
894 * bSetFileTime [I] TRUE: Set file times
895 * FALSE: Get file times
896 *
897 * RETURNS
898 * Success: ERROR_SUCCESS
899 * Failure: other
900 */
901 DWORD WINAPI GetSetFileTimestamp(LPCWSTR lpFileName,
902 LPFILETIME lpCreationTime,
903 LPFILETIME lpLastAccessTime,
904 LPFILETIME lpLastWriteTime,
905 BOOLEAN bSetFileTime)
906 {
907 HANDLE hFile;
908 BOOLEAN bRet;
909 DWORD dwError = ERROR_SUCCESS;
910
911 TRACE("%s %p %p %p %x\n", debugstr_w(lpFileName), lpCreationTime,
912 lpLastAccessTime, lpLastWriteTime, bSetFileTime);
913
914 hFile = CreateFileW(lpFileName,
915 bSetFileTime ? GENERIC_WRITE : GENERIC_READ,
916 FILE_SHARE_READ | FILE_SHARE_WRITE,
917 NULL,
918 OPEN_EXISTING,
919 0,
920 NULL);
921
922 if (hFile == INVALID_HANDLE_VALUE)
923 return GetLastError();
924
925 if (bSetFileTime)
926 bRet = SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
927 else
928 bRet = GetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
929
930 if (bRet == FALSE)
931 dwError = GetLastError();
932
933 CloseHandle(hFile);
934
935 return dwError;
936 }
937
938
939 /**************************************************************************
940 * MyGetFileTitle [SETUPAPI.@]
941 *
942 * Returns a pointer to the last part of a fully qualified file name.
943 *
944 * PARAMS
945 * lpFileName [I] File name
946 *
947 * RETURNS
948 * Pointer to a files name.
949 */
950 LPWSTR WINAPI
951 MyGetFileTitle(LPCWSTR lpFileName)
952 {
953 LPWSTR ptr;
954 LPWSTR ret;
955 WCHAR c;
956
957 TRACE("%s\n", debugstr_w(lpFileName));
958
959 ptr = (LPWSTR)lpFileName;
960 ret = ptr;
961 while (TRUE)
962 {
963 c = *ptr;
964
965 if (c == 0)
966 break;
967
968 ptr++;
969 if (c == (WCHAR)'\\' || c == (WCHAR)'/' || c == (WCHAR)':')
970 ret = ptr;
971 }
972
973 return ret;
974 }
975
976
977 /**************************************************************************
978 * ConcatenatePaths [SETUPAPI.@]
979 *
980 * Concatenates two paths.
981 *
982 * PARAMS
983 * lpPath [I/O] Path to append path to
984 * lpAppend [I] Path to append
985 * dwBufferSize [I] Size of the path buffer
986 * lpRequiredSize [O] Required size for the concatenated path. Optional
987 *
988 * RETURNS
989 * Success: TRUE
990 * Failure: FALSE
991 */
992 BOOL WINAPI
993 ConcatenatePaths(LPWSTR lpPath,
994 LPCWSTR lpAppend,
995 DWORD dwBufferSize,
996 LPDWORD lpRequiredSize)
997 {
998 DWORD dwPathSize;
999 DWORD dwAppendSize;
1000 DWORD dwTotalSize;
1001 BOOL bBackslash = FALSE;
1002
1003 TRACE("%s %s %lu %p\n", debugstr_w(lpPath), debugstr_w(lpAppend),
1004 dwBufferSize, lpRequiredSize);
1005
1006 dwPathSize = lstrlenW(lpPath);
1007
1008 /* Ignore trailing backslash */
1009 if (lpPath[dwPathSize - 1] == (WCHAR)'\\')
1010 dwPathSize--;
1011
1012 dwAppendSize = lstrlenW(lpAppend);
1013
1014 /* Does the source string have a leading backslash? */
1015 if (lpAppend[0] == (WCHAR)'\\')
1016 {
1017 bBackslash = TRUE;
1018 dwAppendSize--;
1019 }
1020
1021 dwTotalSize = dwPathSize + dwAppendSize + 2;
1022 if (lpRequiredSize != NULL)
1023 *lpRequiredSize = dwTotalSize;
1024
1025 /* Append a backslash to the destination string */
1026 if (bBackslash == FALSE)
1027 {
1028 if (dwPathSize < dwBufferSize)
1029 {
1030 lpPath[dwPathSize - 1] = (WCHAR)'\\';
1031 dwPathSize++;
1032 }
1033 }
1034
1035 if (dwPathSize + dwAppendSize < dwBufferSize)
1036 {
1037 lstrcpynW(&lpPath[dwPathSize],
1038 lpAppend,
1039 dwAppendSize);
1040 }
1041
1042 if (dwBufferSize >= dwTotalSize)
1043 lpPath[dwTotalSize - 1] = 0;
1044
1045 return (dwBufferSize >= dwTotalSize);
1046 }
1047
1048
1049 /**************************************************************************
1050 * CenterWindowRelativeToParent [SETUPAPI.@]
1051 *
1052 * Centers a window relative to its parent.
1053 *
1054 * PARAMS
1055 * hwnd [I] Window to center.
1056 *
1057 * RETURNS
1058 * None
1059 */
1060 VOID WINAPI
1061 CenterWindowRelativeToParent(HWND hwnd)
1062 {
1063 HWND hwndOwner;
1064 POINT ptOrigin;
1065 RECT rcWindow;
1066 RECT rcOwner;
1067 INT nWindowWidth, nWindowHeight;
1068 INT nOwnerWidth, nOwnerHeight;
1069 INT posX, posY;
1070
1071 hwndOwner = GetWindow(hwnd, GW_OWNER);
1072 if (hwndOwner == NULL)
1073 return;
1074
1075 ptOrigin.x = 0;
1076 ptOrigin.y = 0;
1077 ClientToScreen(hwndOwner, &ptOrigin);
1078
1079 GetWindowRect(hwnd, &rcWindow);
1080 GetClientRect(hwndOwner, &rcOwner);
1081
1082 nWindowWidth = rcWindow.right - rcWindow.left;
1083 nWindowHeight = rcWindow.bottom - rcWindow.top;
1084
1085 nOwnerWidth = rcOwner.right - rcOwner.left;
1086 nOwnerHeight = rcOwner.bottom - rcOwner.top;
1087
1088 posX = ((nOwnerWidth - nWindowWidth) / 2) + ptOrigin.x;
1089 posY = ((nOwnerHeight - nWindowHeight) / 2) + ptOrigin.y;
1090
1091 MoveWindow(hwnd, posX, posY, nWindowHeight, nWindowWidth, 0);
1092 }
1093
1094
1095 /**************************************************************************
1096 * GetVersionInfoFromImage [SETUPAPI.@]
1097 *
1098 * Retrieves version information for a given file.
1099 *
1100 * PARAMS
1101 * lpFileName [I] File name
1102 * lpFileVersion [O] Pointer to the full file version
1103 * lpVersionVarSize [O] Pointer to the size of the variable version
1104 * information
1105 *
1106 * RETURNS
1107 * Success: TRUE
1108 * Failure: FALSE
1109 */
1110 BOOL WINAPI
1111 GetVersionInfoFromImage(LPWSTR lpFileName,
1112 PULARGE_INTEGER lpFileVersion,
1113 LPWORD lpVersionVarSize)
1114 {
1115 DWORD dwHandle;
1116 DWORD dwSize;
1117 LPVOID lpInfo;
1118 UINT uSize;
1119 VS_FIXEDFILEINFO *lpFixedInfo;
1120 LPWORD lpVarSize;
1121
1122 dwSize = GetFileVersionInfoSizeW(lpFileName, &dwHandle);
1123 if (dwSize == 0)
1124 return FALSE;
1125
1126 lpInfo = MyMalloc(dwSize);
1127 if (lpInfo == NULL)
1128 return FALSE;
1129
1130 if (!GetFileVersionInfoW(lpFileName, 0, dwSize, lpInfo))
1131 {
1132 MyFree(lpInfo);
1133 return FALSE;
1134 }
1135
1136 if (!VerQueryValueW(lpInfo, L"\\",
1137 (LPVOID*)&lpFixedInfo, &uSize))
1138 {
1139 MyFree(lpInfo);
1140 return FALSE;
1141 }
1142
1143 lpFileVersion->LowPart = lpFixedInfo->dwFileVersionLS;
1144 lpFileVersion->HighPart = lpFixedInfo->dwFileVersionMS;
1145
1146 *lpVersionVarSize = 0;
1147 if (!VerQueryValueW(lpInfo, L"\\VerFileInfo\\Translation",
1148 (LPVOID*)&lpVarSize, &uSize))
1149 {
1150 MyFree(lpInfo);
1151 return TRUE;
1152 }
1153
1154 if (uSize >= 4)
1155 {
1156 *lpVersionVarSize = *lpVarSize;
1157 }
1158
1159 MyFree(lpInfo);
1160
1161 return TRUE;
1162 }