Implement SetupDiGetClassImageIndex, SetupDiGetClassImageList, SetupDiGetClassImageLi...
[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 "setupapi_private.h"
22
23 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
24
25 /**************************************************************************
26 * MyFree [SETUPAPI.@]
27 *
28 * Frees an allocated memory block from the process heap.
29 *
30 * PARAMS
31 * lpMem [I] pointer to memory block which will be freed
32 *
33 * RETURNS
34 * None
35 */
36 VOID WINAPI MyFree(LPVOID lpMem)
37 {
38 TRACE("%p\n", lpMem);
39 HeapFree(GetProcessHeap(), 0, lpMem);
40 }
41
42
43 /**************************************************************************
44 * MyMalloc [SETUPAPI.@]
45 *
46 * Allocates memory block from the process heap.
47 *
48 * PARAMS
49 * dwSize [I] size of the allocated memory block
50 *
51 * RETURNS
52 * Success: pointer to allocated memory block
53 * Failure: NULL
54 */
55 LPVOID WINAPI MyMalloc(DWORD dwSize)
56 {
57 TRACE("%lu\n", dwSize);
58 return HeapAlloc(GetProcessHeap(), 0, dwSize);
59 }
60
61
62 /**************************************************************************
63 * MyRealloc [SETUPAPI.@]
64 *
65 * Changes the size of an allocated memory block or allocates a memory
66 * block from the process heap.
67 *
68 * PARAMS
69 * lpSrc [I] pointer to memory block which will be resized
70 * dwSize [I] new size of the memory block
71 *
72 * RETURNS
73 * Success: pointer to the resized memory block
74 * Failure: NULL
75 *
76 * NOTES
77 * If lpSrc is a NULL-pointer, then MyRealloc allocates a memory
78 * block like MyMalloc.
79 */
80 LPVOID WINAPI MyRealloc(LPVOID lpSrc, DWORD dwSize)
81 {
82 TRACE("%p %lu\n", lpSrc, dwSize);
83
84 if (lpSrc == NULL)
85 return HeapAlloc(GetProcessHeap(), 0, dwSize);
86
87 return HeapReAlloc(GetProcessHeap(), 0, lpSrc, dwSize);
88 }
89
90
91 /**************************************************************************
92 * DuplicateString [SETUPAPI.@]
93 *
94 * Duplicates a unicode string.
95 *
96 * PARAMS
97 * lpSrc [I] pointer to the unicode string that will be duplicated
98 *
99 * RETURNS
100 * Success: pointer to the duplicated unicode string
101 * Failure: NULL
102 *
103 * NOTES
104 * Call MyFree() to release the duplicated string.
105 */
106 LPWSTR WINAPI DuplicateString(LPCWSTR lpSrc)
107 {
108 LPWSTR lpDst;
109
110 TRACE("%s\n", debugstr_w(lpSrc));
111
112 lpDst = MyMalloc((lstrlenW(lpSrc) + 1) * sizeof(WCHAR));
113 if (lpDst == NULL)
114 return NULL;
115
116 strcpyW(lpDst, lpSrc);
117
118 return lpDst;
119 }
120
121
122 /**************************************************************************
123 * QueryRegistryValue [SETUPAPI.@]
124 *
125 * Retrieves value data from the registry and allocates memory for the
126 * value data.
127 *
128 * PARAMS
129 * hKey [I] Handle of the key to query
130 * lpValueName [I] Name of value under hkey to query
131 * lpData [O] Destination for the values contents,
132 * lpType [O] Destination for the value type
133 * lpcbData [O] Destination for the size of data
134 *
135 * RETURNS
136 * Success: ERROR_SUCCESS
137 * Failure: Otherwise
138 *
139 * NOTES
140 * Use MyFree to release the lpData buffer.
141 */
142 LONG WINAPI QueryRegistryValue(HKEY hKey,
143 LPCWSTR lpValueName,
144 LPBYTE *lpData,
145 LPDWORD lpType,
146 LPDWORD lpcbData)
147 {
148 LONG lError;
149
150 TRACE("%p %s %p %p %p\n",
151 hKey, debugstr_w(lpValueName), lpData, lpType, lpcbData);
152
153 /* Get required buffer size */
154 *lpcbData = 0;
155 lError = RegQueryValueExW(hKey, lpValueName, 0, lpType, NULL, lpcbData);
156 if (lError != ERROR_SUCCESS)
157 return lError;
158
159 /* Allocate buffer */
160 *lpData = MyMalloc(*lpcbData);
161 if (*lpData == NULL)
162 return ERROR_NOT_ENOUGH_MEMORY;
163
164 /* Query registry value */
165 lError = RegQueryValueExW(hKey, lpValueName, 0, lpType, *lpData, lpcbData);
166 if (lError != ERROR_SUCCESS)
167 MyFree(*lpData);
168
169 return lError;
170 }
171
172
173 /**************************************************************************
174 * IsUserAdmin [SETUPAPI.@]
175 *
176 * Checks whether the current user is a member of the Administrators group.
177 *
178 * PARAMS
179 * None
180 *
181 * RETURNS
182 * Success: TRUE
183 * Failure: FALSE
184 */
185 BOOL WINAPI IsUserAdmin(VOID)
186 {
187 SID_IDENTIFIER_AUTHORITY Authority = {SECURITY_NT_AUTHORITY};
188 HANDLE hToken;
189 DWORD dwSize;
190 PTOKEN_GROUPS lpGroups;
191 PSID lpSid;
192 DWORD i;
193 BOOL bResult = FALSE;
194
195 TRACE("\n");
196
197 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
198 {
199 return FALSE;
200 }
201
202 if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize))
203 {
204 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
205 {
206 CloseHandle(hToken);
207 return FALSE;
208 }
209 }
210
211 lpGroups = MyMalloc(dwSize);
212 if (lpGroups == NULL)
213 {
214 CloseHandle(hToken);
215 return FALSE;
216 }
217
218 if (!GetTokenInformation(hToken, TokenGroups, lpGroups, dwSize, &dwSize))
219 {
220 MyFree(lpGroups);
221 CloseHandle(hToken);
222 return FALSE;
223 }
224
225 CloseHandle(hToken);
226
227 if (!AllocateAndInitializeSid(&Authority, 2, SECURITY_BUILTIN_DOMAIN_RID,
228 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
229 &lpSid))
230 {
231 MyFree(lpGroups);
232 return FALSE;
233 }
234
235 for (i = 0; i < lpGroups->GroupCount; i++)
236 {
237 if (EqualSid(lpSid, &lpGroups->Groups[i].Sid))
238 {
239 bResult = TRUE;
240 break;
241 }
242 }
243
244 FreeSid(lpSid);
245 MyFree(lpGroups);
246
247 return bResult;
248 }
249
250
251 /**************************************************************************
252 * MultiByteToUnicode [SETUPAPI.@]
253 *
254 * Converts a multi-byte string to a Unicode string.
255 *
256 * PARAMS
257 * lpMultiByteStr [I] Multi-byte string to be converted
258 * uCodePage [I] Code page
259 *
260 * RETURNS
261 * Success: pointer to the converted Unicode string
262 * Failure: NULL
263 *
264 * NOTE
265 * Use MyFree to release the returned Unicode string.
266 */
267 LPWSTR WINAPI MultiByteToUnicode(LPCSTR lpMultiByteStr, UINT uCodePage)
268 {
269 LPWSTR lpUnicodeStr;
270 int nLength;
271
272 TRACE("%s %d\n", debugstr_a(lpMultiByteStr), uCodePage);
273
274 nLength = MultiByteToWideChar(uCodePage, 0, lpMultiByteStr,
275 -1, NULL, 0);
276 if (nLength == 0)
277 return NULL;
278
279 lpUnicodeStr = MyMalloc(nLength * sizeof(WCHAR));
280 if (lpUnicodeStr == NULL)
281 {
282 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
283 return NULL;
284 }
285
286 if (!MultiByteToWideChar(uCodePage, 0, lpMultiByteStr,
287 nLength, lpUnicodeStr, nLength))
288 {
289 MyFree(lpUnicodeStr);
290 return NULL;
291 }
292
293 return lpUnicodeStr;
294 }
295
296
297 /**************************************************************************
298 * UnicodeToMultiByte [SETUPAPI.@]
299 *
300 * Converts a Unicode string to a multi-byte string.
301 *
302 * PARAMS
303 * lpUnicodeStr [I] Unicode string to be converted
304 * uCodePage [I] Code page
305 *
306 * RETURNS
307 * Success: pointer to the converted multi-byte string
308 * Failure: NULL
309 *
310 * NOTE
311 * Use MyFree to release the returned multi-byte string.
312 */
313 LPSTR WINAPI UnicodeToMultiByte(LPCWSTR lpUnicodeStr, UINT uCodePage)
314 {
315 LPSTR lpMultiByteStr;
316 int nLength;
317
318 TRACE("%s %d\n", debugstr_w(lpUnicodeStr), uCodePage);
319
320 nLength = WideCharToMultiByte(uCodePage, 0, lpUnicodeStr, -1,
321 NULL, 0, NULL, NULL);
322 if (nLength == 0)
323 return NULL;
324
325 lpMultiByteStr = MyMalloc(nLength);
326 if (lpMultiByteStr == NULL)
327 return NULL;
328
329 if (!WideCharToMultiByte(uCodePage, 0, lpUnicodeStr, -1,
330 lpMultiByteStr, nLength, NULL, NULL))
331 {
332 MyFree(lpMultiByteStr);
333 return NULL;
334 }
335
336 return lpMultiByteStr;
337 }
338
339
340 /**************************************************************************
341 * DoesUserHavePrivilege [SETUPAPI.@]
342 *
343 * Check whether the current user has got a given privilege.
344 *
345 * PARAMS
346 * lpPrivilegeName [I] Name of the privilege to be checked
347 *
348 * RETURNS
349 * Success: TRUE
350 * Failure: FALSE
351 */
352 BOOL WINAPI DoesUserHavePrivilege(LPCWSTR lpPrivilegeName)
353 {
354 HANDLE hToken;
355 DWORD dwSize;
356 PTOKEN_PRIVILEGES lpPrivileges;
357 LUID PrivilegeLuid;
358 DWORD i;
359 BOOL bResult = FALSE;
360
361 TRACE("%s\n", debugstr_w(lpPrivilegeName));
362
363 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
364 return FALSE;
365
366 if (!GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwSize))
367 {
368 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
369 {
370 CloseHandle(hToken);
371 return FALSE;
372 }
373 }
374
375 lpPrivileges = MyMalloc(dwSize);
376 if (lpPrivileges == NULL)
377 {
378 CloseHandle(hToken);
379 return FALSE;
380 }
381
382 if (!GetTokenInformation(hToken, TokenPrivileges, lpPrivileges, dwSize, &dwSize))
383 {
384 MyFree(lpPrivileges);
385 CloseHandle(hToken);
386 return FALSE;
387 }
388
389 CloseHandle(hToken);
390
391 if (!LookupPrivilegeValueW(NULL, lpPrivilegeName, &PrivilegeLuid))
392 {
393 MyFree(lpPrivileges);
394 return FALSE;
395 }
396
397 for (i = 0; i < lpPrivileges->PrivilegeCount; i++)
398 {
399 if (lpPrivileges->Privileges[i].Luid.HighPart == PrivilegeLuid.HighPart &&
400 lpPrivileges->Privileges[i].Luid.LowPart == PrivilegeLuid.LowPart)
401 {
402 bResult = TRUE;
403 }
404 }
405
406 MyFree(lpPrivileges);
407
408 return bResult;
409 }
410
411
412 /**************************************************************************
413 * EnablePrivilege [SETUPAPI.@]
414 *
415 * Enables or disables one of the current users privileges.
416 *
417 * PARAMS
418 * lpPrivilegeName [I] Name of the privilege to be changed
419 * bEnable [I] TRUE: Enables the privilege
420 * FALSE: Disables the privilege
421 *
422 * RETURNS
423 * Success: TRUE
424 * Failure: FALSE
425 */
426 BOOL WINAPI EnablePrivilege(LPCWSTR lpPrivilegeName, BOOL bEnable)
427 {
428 TOKEN_PRIVILEGES Privileges;
429 HANDLE hToken;
430 BOOL bResult;
431
432 TRACE("%s %s\n", debugstr_w(lpPrivilegeName), bEnable ? "TRUE" : "FALSE");
433
434 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
435 return FALSE;
436
437 Privileges.PrivilegeCount = 1;
438 Privileges.Privileges[0].Attributes = (bEnable) ? SE_PRIVILEGE_ENABLED : 0;
439
440 if (!LookupPrivilegeValueW(NULL, lpPrivilegeName,
441 &Privileges.Privileges[0].Luid))
442 {
443 CloseHandle(hToken);
444 return FALSE;
445 }
446
447 bResult = AdjustTokenPrivileges(hToken, FALSE, &Privileges, 0, NULL, NULL);
448
449 CloseHandle(hToken);
450
451 return bResult;
452 }
453
454
455 /**************************************************************************
456 * DelayedMove [SETUPAPI.@]
457 *
458 * Moves a file upon the next reboot.
459 *
460 * PARAMS
461 * lpExistingFileName [I] Current file name
462 * lpNewFileName [I] New file name
463 *
464 * RETURNS
465 * Success: TRUE
466 * Failure: FALSE
467 */
468 BOOL WINAPI DelayedMove(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
469 {
470 if (OsVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
471 {
472 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
473 return FALSE;
474 }
475
476 return MoveFileExW(lpExistingFileName, lpNewFileName,
477 MOVEFILE_REPLACE_EXISTING | MOVEFILE_DELAY_UNTIL_REBOOT);
478 }
479
480
481 /**************************************************************************
482 * FileExists [SETUPAPI.@]
483 *
484 * Checks whether a file exists.
485 *
486 * PARAMS
487 * lpFileName [I] Name of the file to check
488 * lpNewFileName [O] Optional information about the existing file
489 *
490 * RETURNS
491 * Success: TRUE
492 * Failure: FALSE
493 */
494 BOOL WINAPI FileExists(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFileFindData)
495 {
496 WIN32_FIND_DATAW FindData;
497 HANDLE hFind;
498 UINT uErrorMode;
499 DWORD dwError;
500
501 uErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
502
503 hFind = FindFirstFileW(lpFileName, &FindData);
504 if (hFind == INVALID_HANDLE_VALUE)
505 {
506 dwError = GetLastError();
507 SetErrorMode(uErrorMode);
508 SetLastError(dwError);
509 return FALSE;
510 }
511
512 FindClose(hFind);
513
514 if (lpFileFindData)
515 memcpy(lpFileFindData, &FindData, sizeof(WIN32_FIND_DATAW));
516
517 SetErrorMode(uErrorMode);
518
519 return TRUE;
520 }
521
522
523 /**************************************************************************
524 * CaptureStringArg [SETUPAPI.@]
525 *
526 * Captures a UNICODE string.
527 *
528 * PARAMS
529 * lpSrc [I] UNICODE string to be captured
530 * lpDst [O] Pointer to the captured UNICODE string
531 *
532 * RETURNS
533 * Success: ERROR_SUCCESS
534 * Failure: ERROR_INVALID_PARAMETER
535 *
536 * NOTE
537 * Call MyFree to release the captured UNICODE string.
538 */
539 DWORD WINAPI CaptureStringArg(LPCWSTR pSrc, LPWSTR *pDst)
540 {
541 if (pDst == NULL)
542 return ERROR_INVALID_PARAMETER;
543
544 *pDst = DuplicateString(pSrc);
545
546 return ERROR_SUCCESS;
547 }
548
549
550 /**************************************************************************
551 * CaptureAndConvertAnsiArg [SETUPAPI.@]
552 *
553 * Captures an ANSI string and converts it to a UNICODE string.
554 *
555 * PARAMS
556 * lpSrc [I] ANSI string to be captured
557 * lpDst [O] Pointer to the captured UNICODE string
558 *
559 * RETURNS
560 * Success: ERROR_SUCCESS
561 * Failure: ERROR_INVALID_PARAMETER
562 *
563 * NOTE
564 * Call MyFree to release the captured UNICODE string.
565 */
566 DWORD WINAPI CaptureAndConvertAnsiArg(LPCSTR pSrc, LPWSTR *pDst)
567 {
568 if (pDst == NULL)
569 return ERROR_INVALID_PARAMETER;
570
571 *pDst = MultiByteToUnicode(pSrc, CP_ACP);
572
573 return ERROR_SUCCESS;
574 }
575
576
577 /**************************************************************************
578 * OpenAndMapFileForRead [SETUPAPI.@]
579 *
580 * Open and map a file to a buffer.
581 *
582 * PARAMS
583 * lpFileName [I] Name of the file to be opened
584 * lpSize [O] Pointer to the file size
585 * lpFile [0] Pointer to the file handle
586 * lpMapping [0] Pointer to the mapping handle
587 * lpBuffer [0] Pointer to the file buffer
588 *
589 * RETURNS
590 * Success: ERROR_SUCCESS
591 * Failure: Other
592 *
593 * NOTE
594 * Call UnmapAndCloseFile to release the file.
595 */
596 DWORD WINAPI OpenAndMapFileForRead(LPCWSTR lpFileName,
597 LPDWORD lpSize,
598 LPHANDLE lpFile,
599 LPHANDLE lpMapping,
600 LPVOID *lpBuffer)
601 {
602 DWORD dwError;
603
604 TRACE("%s %p %p %p %p\n",
605 debugstr_w(lpFileName), lpSize, lpFile, lpMapping, lpBuffer);
606
607 *lpFile = CreateFileW(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
608 OPEN_EXISTING, 0, NULL);
609 if (*lpFile == INVALID_HANDLE_VALUE)
610 return GetLastError();
611
612 *lpSize = GetFileSize(*lpFile, NULL);
613 if (*lpSize == INVALID_FILE_SIZE)
614 {
615 dwError = GetLastError();
616 CloseHandle(*lpFile);
617 return dwError;
618 }
619
620 *lpMapping = CreateFileMappingW(*lpFile, NULL, PAGE_READONLY, 0,
621 *lpSize, NULL);
622 if (*lpMapping == NULL)
623 {
624 dwError = GetLastError();
625 CloseHandle(*lpFile);
626 return dwError;
627 }
628
629 *lpBuffer = MapViewOfFile(*lpMapping, FILE_MAP_READ, 0, 0, *lpSize);
630 if (*lpBuffer == NULL)
631 {
632 dwError = GetLastError();
633 CloseHandle(*lpMapping);
634 CloseHandle(*lpFile);
635 return dwError;
636 }
637
638 return ERROR_SUCCESS;
639 }
640
641
642 /**************************************************************************
643 * UnmapAndCloseFile [SETUPAPI.@]
644 *
645 * Unmap and close a mapped file.
646 *
647 * PARAMS
648 * hFile [I] Handle to the file
649 * hMapping [I] Handle to the file mapping
650 * lpBuffer [I] Pointer to the file buffer
651 *
652 * RETURNS
653 * Success: TRUE
654 * Failure: FALSE
655 */
656 BOOL WINAPI UnmapAndCloseFile(HANDLE hFile, HANDLE hMapping, LPVOID lpBuffer)
657 {
658 TRACE("%p %p %p\n",
659 hFile, hMapping, lpBuffer);
660
661 if (!UnmapViewOfFile(lpBuffer))
662 return FALSE;
663
664 if (!CloseHandle(hMapping))
665 return FALSE;
666
667 if (!CloseHandle(hFile))
668 return FALSE;
669
670 return TRUE;
671 }
672
673
674 /**************************************************************************
675 * StampFileSecurity [SETUPAPI.@]
676 *
677 * Assign a new security descriptor to the given file.
678 *
679 * PARAMS
680 * lpFileName [I] Name of the file
681 * pSecurityDescriptor [I] New security descriptor
682 *
683 * RETURNS
684 * Success: ERROR_SUCCESS
685 * Failure: other
686 */
687 DWORD WINAPI StampFileSecurity(LPCWSTR lpFileName, PSECURITY_DESCRIPTOR pSecurityDescriptor)
688 {
689 TRACE("%s %p\n", debugstr_w(lpFileName), pSecurityDescriptor);
690
691 if (!SetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION |
692 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
693 pSecurityDescriptor))
694 return GetLastError();
695
696 return ERROR_SUCCESS;
697 }
698
699
700 /**************************************************************************
701 * TakeOwnershipOfFile [SETUPAPI.@]
702 *
703 * Takes the ownership of the given file.
704 *
705 * PARAMS
706 * lpFileName [I] Name of the file
707 *
708 * RETURNS
709 * Success: ERROR_SUCCESS
710 * Failure: other
711 */
712 DWORD WINAPI TakeOwnershipOfFile(LPCWSTR lpFileName)
713 {
714 SECURITY_DESCRIPTOR SecDesc;
715 HANDLE hToken = NULL;
716 PTOKEN_OWNER pOwner = NULL;
717 DWORD dwError;
718 DWORD dwSize;
719
720 TRACE("%s\n", debugstr_w(lpFileName));
721
722 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
723 return GetLastError();
724
725 if (!GetTokenInformation(hToken, TokenOwner, NULL, 0, &dwSize))
726 {
727 goto fail;
728 }
729
730 pOwner = (PTOKEN_OWNER)MyMalloc(dwSize);
731 if (pOwner == NULL)
732 {
733 CloseHandle(hToken);
734 return ERROR_NOT_ENOUGH_MEMORY;
735 }
736
737 if (!GetTokenInformation(hToken, TokenOwner, pOwner, dwSize, &dwSize))
738 {
739 goto fail;
740 }
741
742 if (!InitializeSecurityDescriptor(&SecDesc, SECURITY_DESCRIPTOR_REVISION))
743 {
744 goto fail;
745 }
746
747 if (!SetSecurityDescriptorOwner(&SecDesc, pOwner->Owner, FALSE))
748 {
749 goto fail;
750 }
751
752 if (!SetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION, &SecDesc))
753 {
754 goto fail;
755 }
756
757 MyFree(pOwner);
758 CloseHandle(hToken);
759
760 return ERROR_SUCCESS;
761
762 fail:;
763 dwError = GetLastError();
764
765 if (pOwner != NULL)
766 MyFree(pOwner);
767
768 if (hToken != NULL)
769 CloseHandle(hToken);
770
771 return dwError;
772 }
773
774
775 /**************************************************************************
776 * RetreiveFileSecurity [SETUPAPI.@]
777 *
778 * Retrieve the security descriptor that is associated with the given file.
779 *
780 * PARAMS
781 * lpFileName [I] Name of the file
782 *
783 * RETURNS
784 * Success: ERROR_SUCCESS
785 * Failure: other
786 */
787 DWORD WINAPI RetreiveFileSecurity(LPCWSTR lpFileName,
788 PSECURITY_DESCRIPTOR *pSecurityDescriptor)
789 {
790 PSECURITY_DESCRIPTOR SecDesc;
791 DWORD dwSize = 0x100;
792 DWORD dwError;
793
794 TRACE("%s %p\n", debugstr_w(lpFileName), pSecurityDescriptor);
795
796 SecDesc = (PSECURITY_DESCRIPTOR)MyMalloc(dwSize);
797 if (SecDesc == NULL)
798 return ERROR_NOT_ENOUGH_MEMORY;
799
800 if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION |
801 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
802 SecDesc, dwSize, &dwSize))
803 {
804 *pSecurityDescriptor = SecDesc;
805 return ERROR_SUCCESS;
806 }
807
808 dwError = GetLastError();
809 if (dwError != ERROR_INSUFFICIENT_BUFFER)
810 {
811 MyFree(SecDesc);
812 return dwError;
813 }
814
815 SecDesc = (PSECURITY_DESCRIPTOR)MyRealloc(SecDesc, dwSize);
816 if (SecDesc == NULL)
817 return ERROR_NOT_ENOUGH_MEMORY;
818
819 if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION |
820 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
821 SecDesc, dwSize, &dwSize))
822 {
823 *pSecurityDescriptor = SecDesc;
824 return ERROR_SUCCESS;
825 }
826
827 dwError = GetLastError();
828 MyFree(SecDesc);
829
830 return dwError;
831 }
832
833
834 /**************************************************************************
835 * AssertFail [SETUPAPI.@]
836 *
837 * Display an assertion message.
838 *
839 * PARAMS
840 * lpFile [I] File name
841 * uLine [I] Line number
842 * lpMessage [I] Assertion message
843 *
844 * RETURNS
845 * Nothing
846 */
847 VOID WINAPI AssertFail(LPSTR lpFile, UINT uLine, LPSTR lpMessage)
848 {
849 CHAR szModule[MAX_PATH];
850 CHAR szBuffer[2048];
851 LPSTR lpName;
852 // LPSTR lpBuffer;
853
854 TRACE("%s %u %s\n", lpFile, uLine, lpMessage);
855
856 GetModuleFileNameA(hInstance, szModule, MAX_PATH);
857 lpName = strrchr(szModule, '\\');
858 if (lpName != NULL)
859 lpName++;
860 else
861 lpName = szModule;
862
863 wsprintfA(szBuffer,
864 "Assertion failure at line %u in file %s: %s\n\nCall DebugBreak()?",
865 uLine, lpFile, lpMessage);
866
867 if (MessageBoxA(NULL, szBuffer, lpName, MB_SETFOREGROUND |
868 MB_TASKMODAL | MB_ICONERROR | MB_YESNO) == IDYES)
869 DebugBreak();
870 }
871
872
873 /**************************************************************************
874 * GetSetFileTimestamp [SETUPAPI.@]
875 *
876 * Gets or sets a files timestamp.
877 *
878 * PARAMS
879 * lpFileName [I] File name
880 * lpCreationTime [I/O] Creation time
881 * lpLastAccessTime [I/O] Last access time
882 * lpLastWriteTime [I/O] Last write time
883 * bSetFileTime [I] TRUE: Set file times
884 * FALSE: Get file times
885 *
886 * RETURNS
887 * Success: ERROR_SUCCESS
888 * Failure: other
889 */
890 DWORD WINAPI GetSetFileTimestamp(LPCWSTR lpFileName,
891 LPFILETIME lpCreationTime,
892 LPFILETIME lpLastAccessTime,
893 LPFILETIME lpLastWriteTime,
894 BOOLEAN bSetFileTime)
895 {
896 HANDLE hFile;
897 BOOLEAN bRet;
898 DWORD dwError = ERROR_SUCCESS;
899
900 TRACE("%s %p %p %p %x\n", debugstr_w(lpFileName), lpCreationTime,
901 lpLastAccessTime, lpLastWriteTime, bSetFileTime);
902
903 hFile = CreateFileW(lpFileName,
904 bSetFileTime ? GENERIC_WRITE : GENERIC_READ,
905 FILE_SHARE_READ | FILE_SHARE_WRITE,
906 NULL,
907 OPEN_EXISTING,
908 0,
909 NULL);
910
911 if (hFile == INVALID_HANDLE_VALUE)
912 return GetLastError();
913
914 if (bSetFileTime)
915 bRet = SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
916 else
917 bRet = GetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
918
919 if (bRet == FALSE)
920 dwError = GetLastError();
921
922 CloseHandle(hFile);
923
924 return dwError;
925 }
926
927
928 /**************************************************************************
929 * MyGetFileTitle [SETUPAPI.@]
930 *
931 * Returns a pointer to the last part of a fully qualified file name.
932 *
933 * PARAMS
934 * lpFileName [I] File name
935 *
936 * RETURNS
937 * Pointer to a files name.
938 */
939 LPWSTR WINAPI
940 MyGetFileTitle(LPCWSTR lpFileName)
941 {
942 LPWSTR ptr;
943 LPWSTR ret;
944 WCHAR c;
945
946 TRACE("%s\n", debugstr_w(lpFileName));
947
948 ptr = (LPWSTR)lpFileName;
949 ret = ptr;
950 while (TRUE)
951 {
952 c = *ptr;
953
954 if (c == 0)
955 break;
956
957 ptr++;
958 if (c == (WCHAR)'\\' || c == (WCHAR)'/' || c == (WCHAR)':')
959 ret = ptr;
960 }
961
962 return ret;
963 }
964
965
966 /**************************************************************************
967 * ConcatenatePaths [SETUPAPI.@]
968 *
969 * Concatenates two paths.
970 *
971 * PARAMS
972 * lpPath [I/O] Path to append path to
973 * lpAppend [I] Path to append
974 * dwBufferSize [I] Size of the path buffer
975 * lpRequiredSize [O] Required size for the concatenated path. Optional
976 *
977 * RETURNS
978 * Success: TRUE
979 * Failure: FALSE
980 */
981 BOOL WINAPI
982 ConcatenatePaths(LPWSTR lpPath,
983 LPCWSTR lpAppend,
984 DWORD dwBufferSize,
985 LPDWORD lpRequiredSize)
986 {
987 DWORD dwPathSize;
988 DWORD dwAppendSize;
989 DWORD dwTotalSize;
990 BOOL bBackslash = FALSE;
991
992 TRACE("%s %s %lu %p\n", debugstr_w(lpPath), debugstr_w(lpAppend),
993 dwBufferSize, lpRequiredSize);
994
995 dwPathSize = lstrlenW(lpPath);
996
997 /* Ignore trailing backslash */
998 if (lpPath[dwPathSize - 1] == (WCHAR)'\\')
999 dwPathSize--;
1000
1001 dwAppendSize = lstrlenW(lpAppend);
1002
1003 /* Does the source string have a leading backslash? */
1004 if (lpAppend[0] == (WCHAR)'\\')
1005 {
1006 bBackslash = TRUE;
1007 dwAppendSize--;
1008 }
1009
1010 dwTotalSize = dwPathSize + dwAppendSize + 2;
1011 if (lpRequiredSize != NULL)
1012 *lpRequiredSize = dwTotalSize;
1013
1014 /* Append a backslash to the destination string */
1015 if (bBackslash == FALSE)
1016 {
1017 if (dwPathSize < dwBufferSize)
1018 {
1019 lpPath[dwPathSize - 1] = (WCHAR)'\\';
1020 dwPathSize++;
1021 }
1022 }
1023
1024 if (dwPathSize + dwAppendSize < dwBufferSize)
1025 {
1026 lstrcpynW(&lpPath[dwPathSize],
1027 lpAppend,
1028 dwAppendSize);
1029 }
1030
1031 if (dwBufferSize >= dwTotalSize)
1032 lpPath[dwTotalSize - 1] = 0;
1033
1034 return (dwBufferSize >= dwTotalSize);
1035 }
1036
1037
1038 /**************************************************************************
1039 * CenterWindowRelativeToParent [SETUPAPI.@]
1040 *
1041 * Centers a window relative to its parent.
1042 *
1043 * PARAMS
1044 * hwnd [I] Window to center.
1045 *
1046 * RETURNS
1047 * None
1048 */
1049 VOID WINAPI
1050 CenterWindowRelativeToParent(HWND hwnd)
1051 {
1052 HWND hwndOwner;
1053 POINT ptOrigin;
1054 RECT rcWindow;
1055 RECT rcOwner;
1056 INT nWindowWidth, nWindowHeight;
1057 INT nOwnerWidth, nOwnerHeight;
1058 INT posX, posY;
1059
1060 hwndOwner = GetWindow(hwnd, GW_OWNER);
1061 if (hwndOwner == NULL)
1062 return;
1063
1064 ptOrigin.x = 0;
1065 ptOrigin.y = 0;
1066 ClientToScreen(hwndOwner, &ptOrigin);
1067
1068 GetWindowRect(hwnd, &rcWindow);
1069 GetClientRect(hwndOwner, &rcOwner);
1070
1071 nWindowWidth = rcWindow.right - rcWindow.left;
1072 nWindowHeight = rcWindow.bottom - rcWindow.top;
1073
1074 nOwnerWidth = rcOwner.right - rcOwner.left;
1075 nOwnerHeight = rcOwner.bottom - rcOwner.top;
1076
1077 posX = ((nOwnerWidth - nWindowWidth) / 2) + ptOrigin.x;
1078 posY = ((nOwnerHeight - nWindowHeight) / 2) + ptOrigin.y;
1079
1080 MoveWindow(hwnd, posX, posY, nWindowHeight, nWindowWidth, 0);
1081 }
1082
1083
1084 /**************************************************************************
1085 * GetVersionInfoFromImage [SETUPAPI.@]
1086 *
1087 * Retrieves version information for a given file.
1088 *
1089 * PARAMS
1090 * lpFileName [I] File name
1091 * lpFileVersion [O] Pointer to the full file version
1092 * lpVersionVarSize [O] Pointer to the size of the variable version
1093 * information
1094 *
1095 * RETURNS
1096 * Success: TRUE
1097 * Failure: FALSE
1098 */
1099 BOOL WINAPI
1100 GetVersionInfoFromImage(LPWSTR lpFileName,
1101 PULARGE_INTEGER lpFileVersion,
1102 LPWORD lpVersionVarSize)
1103 {
1104 DWORD dwHandle;
1105 DWORD dwSize;
1106 LPVOID lpInfo;
1107 UINT uSize;
1108 VS_FIXEDFILEINFO *lpFixedInfo;
1109 LPWORD lpVarSize;
1110
1111 dwSize = GetFileVersionInfoSizeW(lpFileName, &dwHandle);
1112 if (dwSize == 0)
1113 return FALSE;
1114
1115 lpInfo = MyMalloc(dwSize);
1116 if (lpInfo == NULL)
1117 return FALSE;
1118
1119 if (!GetFileVersionInfoW(lpFileName, 0, dwSize, lpInfo))
1120 {
1121 MyFree(lpInfo);
1122 return FALSE;
1123 }
1124
1125 if (!VerQueryValueW(lpInfo, L"\\",
1126 (LPVOID*)&lpFixedInfo, &uSize))
1127 {
1128 MyFree(lpInfo);
1129 return FALSE;
1130 }
1131
1132 lpFileVersion->LowPart = lpFixedInfo->dwFileVersionLS;
1133 lpFileVersion->HighPart = lpFixedInfo->dwFileVersionMS;
1134
1135 *lpVersionVarSize = 0;
1136 if (!VerQueryValueW(lpInfo, L"\\VerFileInfo\\Translation",
1137 (LPVOID*)&lpVarSize, &uSize))
1138 {
1139 MyFree(lpInfo);
1140 return TRUE;
1141 }
1142
1143 if (uSize >= 4)
1144 {
1145 *lpVersionVarSize = *lpVarSize;
1146 }
1147
1148 MyFree(lpInfo);
1149
1150 return TRUE;
1151 }