add stub for SetupDiSetClassInstallParamsW
[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 return NULL;
282
283 if (!MultiByteToWideChar(uCodePage, 0, lpMultiByteStr,
284 nLength, lpUnicodeStr, nLength))
285 {
286 MyFree(lpUnicodeStr);
287 return NULL;
288 }
289
290 return lpUnicodeStr;
291 }
292
293
294 /**************************************************************************
295 * UnicodeToMultiByte [SETUPAPI.@]
296 *
297 * Converts a Unicode string to a multi-byte string.
298 *
299 * PARAMS
300 * lpUnicodeStr [I] Unicode string to be converted
301 * uCodePage [I] Code page
302 *
303 * RETURNS
304 * Success: pointer to the converted multi-byte string
305 * Failure: NULL
306 *
307 * NOTE
308 * Use MyFree to release the returned multi-byte string.
309 */
310 LPSTR WINAPI UnicodeToMultiByte(LPCWSTR lpUnicodeStr, UINT uCodePage)
311 {
312 LPSTR lpMultiByteStr;
313 int nLength;
314
315 TRACE("%s %d\n", debugstr_w(lpUnicodeStr), uCodePage);
316
317 nLength = WideCharToMultiByte(uCodePage, 0, lpUnicodeStr, -1,
318 NULL, 0, NULL, NULL);
319 if (nLength == 0)
320 return NULL;
321
322 lpMultiByteStr = MyMalloc(nLength);
323 if (lpMultiByteStr == NULL)
324 return NULL;
325
326 if (!WideCharToMultiByte(uCodePage, 0, lpUnicodeStr, -1,
327 lpMultiByteStr, nLength, NULL, NULL))
328 {
329 MyFree(lpMultiByteStr);
330 return NULL;
331 }
332
333 return lpMultiByteStr;
334 }
335
336
337 /**************************************************************************
338 * DoesUserHavePrivilege [SETUPAPI.@]
339 *
340 * Check whether the current user has got a given privilege.
341 *
342 * PARAMS
343 * lpPrivilegeName [I] Name of the privilege to be checked
344 *
345 * RETURNS
346 * Success: TRUE
347 * Failure: FALSE
348 */
349 BOOL WINAPI DoesUserHavePrivilege(LPCWSTR lpPrivilegeName)
350 {
351 HANDLE hToken;
352 DWORD dwSize;
353 PTOKEN_PRIVILEGES lpPrivileges;
354 LUID PrivilegeLuid;
355 DWORD i;
356 BOOL bResult = FALSE;
357
358 TRACE("%s\n", debugstr_w(lpPrivilegeName));
359
360 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
361 return FALSE;
362
363 if (!GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwSize))
364 {
365 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
366 {
367 CloseHandle(hToken);
368 return FALSE;
369 }
370 }
371
372 lpPrivileges = MyMalloc(dwSize);
373 if (lpPrivileges == NULL)
374 {
375 CloseHandle(hToken);
376 return FALSE;
377 }
378
379 if (!GetTokenInformation(hToken, TokenPrivileges, lpPrivileges, dwSize, &dwSize))
380 {
381 MyFree(lpPrivileges);
382 CloseHandle(hToken);
383 return FALSE;
384 }
385
386 CloseHandle(hToken);
387
388 if (!LookupPrivilegeValueW(NULL, lpPrivilegeName, &PrivilegeLuid))
389 {
390 MyFree(lpPrivileges);
391 return FALSE;
392 }
393
394 for (i = 0; i < lpPrivileges->PrivilegeCount; i++)
395 {
396 if (lpPrivileges->Privileges[i].Luid.HighPart == PrivilegeLuid.HighPart &&
397 lpPrivileges->Privileges[i].Luid.LowPart == PrivilegeLuid.LowPart)
398 {
399 bResult = TRUE;
400 }
401 }
402
403 MyFree(lpPrivileges);
404
405 return bResult;
406 }
407
408
409 /**************************************************************************
410 * EnablePrivilege [SETUPAPI.@]
411 *
412 * Enables or disables one of the current users privileges.
413 *
414 * PARAMS
415 * lpPrivilegeName [I] Name of the privilege to be changed
416 * bEnable [I] TRUE: Enables the privilege
417 * FALSE: Disables the privilege
418 *
419 * RETURNS
420 * Success: TRUE
421 * Failure: FALSE
422 */
423 BOOL WINAPI EnablePrivilege(LPCWSTR lpPrivilegeName, BOOL bEnable)
424 {
425 TOKEN_PRIVILEGES Privileges;
426 HANDLE hToken;
427 BOOL bResult;
428
429 TRACE("%s %s\n", debugstr_w(lpPrivilegeName), bEnable ? "TRUE" : "FALSE");
430
431 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
432 return FALSE;
433
434 Privileges.PrivilegeCount = 1;
435 Privileges.Privileges[0].Attributes = (bEnable) ? SE_PRIVILEGE_ENABLED : 0;
436
437 if (!LookupPrivilegeValueW(NULL, lpPrivilegeName,
438 &Privileges.Privileges[0].Luid))
439 {
440 CloseHandle(hToken);
441 return FALSE;
442 }
443
444 bResult = AdjustTokenPrivileges(hToken, FALSE, &Privileges, 0, NULL, NULL);
445
446 CloseHandle(hToken);
447
448 return bResult;
449 }
450
451
452 /**************************************************************************
453 * DelayedMove [SETUPAPI.@]
454 *
455 * Moves a file upon the next reboot.
456 *
457 * PARAMS
458 * lpExistingFileName [I] Current file name
459 * lpNewFileName [I] New file name
460 *
461 * RETURNS
462 * Success: TRUE
463 * Failure: FALSE
464 */
465 BOOL WINAPI DelayedMove(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
466 {
467 if (OsVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
468 {
469 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
470 return FALSE;
471 }
472
473 return MoveFileExW(lpExistingFileName, lpNewFileName,
474 MOVEFILE_REPLACE_EXISTING | MOVEFILE_DELAY_UNTIL_REBOOT);
475 }
476
477
478 /**************************************************************************
479 * FileExists [SETUPAPI.@]
480 *
481 * Checks whether a file exists.
482 *
483 * PARAMS
484 * lpFileName [I] Name of the file to check
485 * lpNewFileName [O] Optional information about the existing file
486 *
487 * RETURNS
488 * Success: TRUE
489 * Failure: FALSE
490 */
491 BOOL WINAPI FileExists(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFileFindData)
492 {
493 WIN32_FIND_DATAW FindData;
494 HANDLE hFind;
495 UINT uErrorMode;
496 DWORD dwError;
497
498 uErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
499
500 hFind = FindFirstFileW(lpFileName, &FindData);
501 if (hFind == INVALID_HANDLE_VALUE)
502 {
503 dwError = GetLastError();
504 SetErrorMode(uErrorMode);
505 SetLastError(dwError);
506 return FALSE;
507 }
508
509 FindClose(hFind);
510
511 if (lpFileFindData)
512 memcpy(lpFileFindData, &FindData, sizeof(WIN32_FIND_DATAW));
513
514 SetErrorMode(uErrorMode);
515
516 return TRUE;
517 }
518
519
520 /**************************************************************************
521 * CaptureStringArg [SETUPAPI.@]
522 *
523 * Captures a UNICODE string.
524 *
525 * PARAMS
526 * lpSrc [I] UNICODE string to be captured
527 * lpDst [O] Pointer to the captured UNICODE string
528 *
529 * RETURNS
530 * Success: ERROR_SUCCESS
531 * Failure: ERROR_INVALID_PARAMETER
532 *
533 * NOTE
534 * Call MyFree to release the captured UNICODE string.
535 */
536 DWORD WINAPI CaptureStringArg(LPCWSTR pSrc, LPWSTR *pDst)
537 {
538 if (pDst == NULL)
539 return ERROR_INVALID_PARAMETER;
540
541 *pDst = DuplicateString(pSrc);
542
543 return ERROR_SUCCESS;
544 }
545
546
547 /**************************************************************************
548 * CaptureAndConvertAnsiArg [SETUPAPI.@]
549 *
550 * Captures an ANSI string and converts it to a UNICODE string.
551 *
552 * PARAMS
553 * lpSrc [I] ANSI string to be captured
554 * lpDst [O] Pointer to the captured UNICODE string
555 *
556 * RETURNS
557 * Success: ERROR_SUCCESS
558 * Failure: ERROR_INVALID_PARAMETER
559 *
560 * NOTE
561 * Call MyFree to release the captured UNICODE string.
562 */
563 DWORD WINAPI CaptureAndConvertAnsiArg(LPCSTR pSrc, LPWSTR *pDst)
564 {
565 if (pDst == NULL)
566 return ERROR_INVALID_PARAMETER;
567
568 *pDst = MultiByteToUnicode(pSrc, CP_ACP);
569
570 return ERROR_SUCCESS;
571 }
572
573
574 /**************************************************************************
575 * OpenAndMapFileForRead [SETUPAPI.@]
576 *
577 * Open and map a file to a buffer.
578 *
579 * PARAMS
580 * lpFileName [I] Name of the file to be opened
581 * lpSize [O] Pointer to the file size
582 * lpFile [0] Pointer to the file handle
583 * lpMapping [0] Pointer to the mapping handle
584 * lpBuffer [0] Pointer to the file buffer
585 *
586 * RETURNS
587 * Success: ERROR_SUCCESS
588 * Failure: Other
589 *
590 * NOTE
591 * Call UnmapAndCloseFile to release the file.
592 */
593 DWORD WINAPI OpenAndMapFileForRead(LPCWSTR lpFileName,
594 LPDWORD lpSize,
595 LPHANDLE lpFile,
596 LPHANDLE lpMapping,
597 LPVOID *lpBuffer)
598 {
599 DWORD dwError;
600
601 TRACE("%s %p %p %p %p\n",
602 debugstr_w(lpFileName), lpSize, lpFile, lpMapping, lpBuffer);
603
604 *lpFile = CreateFileW(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
605 OPEN_EXISTING, 0, NULL);
606 if (*lpFile == INVALID_HANDLE_VALUE)
607 return GetLastError();
608
609 *lpSize = GetFileSize(*lpFile, NULL);
610 if (*lpSize == INVALID_FILE_SIZE)
611 {
612 dwError = GetLastError();
613 CloseHandle(*lpFile);
614 return dwError;
615 }
616
617 *lpMapping = CreateFileMappingW(*lpFile, NULL, PAGE_READONLY, 0,
618 *lpSize, NULL);
619 if (*lpMapping == NULL)
620 {
621 dwError = GetLastError();
622 CloseHandle(*lpFile);
623 return dwError;
624 }
625
626 *lpBuffer = MapViewOfFile(*lpMapping, FILE_MAP_READ, 0, 0, *lpSize);
627 if (*lpBuffer == NULL)
628 {
629 dwError = GetLastError();
630 CloseHandle(*lpMapping);
631 CloseHandle(*lpFile);
632 return dwError;
633 }
634
635 return ERROR_SUCCESS;
636 }
637
638
639 /**************************************************************************
640 * UnmapAndCloseFile [SETUPAPI.@]
641 *
642 * Unmap and close a mapped file.
643 *
644 * PARAMS
645 * hFile [I] Handle to the file
646 * hMapping [I] Handle to the file mapping
647 * lpBuffer [I] Pointer to the file buffer
648 *
649 * RETURNS
650 * Success: TRUE
651 * Failure: FALSE
652 */
653 BOOL WINAPI UnmapAndCloseFile(HANDLE hFile, HANDLE hMapping, LPVOID lpBuffer)
654 {
655 TRACE("%p %p %p\n",
656 hFile, hMapping, lpBuffer);
657
658 if (!UnmapViewOfFile(lpBuffer))
659 return FALSE;
660
661 if (!CloseHandle(hMapping))
662 return FALSE;
663
664 if (!CloseHandle(hFile))
665 return FALSE;
666
667 return TRUE;
668 }
669
670
671 /**************************************************************************
672 * StampFileSecurity [SETUPAPI.@]
673 *
674 * Assign a new security descriptor to the given file.
675 *
676 * PARAMS
677 * lpFileName [I] Name of the file
678 * pSecurityDescriptor [I] New security descriptor
679 *
680 * RETURNS
681 * Success: ERROR_SUCCESS
682 * Failure: other
683 */
684 DWORD WINAPI StampFileSecurity(LPCWSTR lpFileName, PSECURITY_DESCRIPTOR pSecurityDescriptor)
685 {
686 TRACE("%s %p\n", debugstr_w(lpFileName), pSecurityDescriptor);
687
688 if (!SetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION |
689 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
690 pSecurityDescriptor))
691 return GetLastError();
692
693 return ERROR_SUCCESS;
694 }
695
696
697 /**************************************************************************
698 * TakeOwnershipOfFile [SETUPAPI.@]
699 *
700 * Takes the ownership of the given file.
701 *
702 * PARAMS
703 * lpFileName [I] Name of the file
704 *
705 * RETURNS
706 * Success: ERROR_SUCCESS
707 * Failure: other
708 */
709 DWORD WINAPI TakeOwnershipOfFile(LPCWSTR lpFileName)
710 {
711 SECURITY_DESCRIPTOR SecDesc;
712 HANDLE hToken = NULL;
713 PTOKEN_OWNER pOwner = NULL;
714 DWORD dwError;
715 DWORD dwSize;
716
717 TRACE("%s\n", debugstr_w(lpFileName));
718
719 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
720 return GetLastError();
721
722 if (!GetTokenInformation(hToken, TokenOwner, NULL, 0, &dwSize))
723 {
724 goto fail;
725 }
726
727 pOwner = (PTOKEN_OWNER)MyMalloc(dwSize);
728 if (pOwner == NULL)
729 {
730 CloseHandle(hToken);
731 return ERROR_NOT_ENOUGH_MEMORY;
732 }
733
734 if (!GetTokenInformation(hToken, TokenOwner, pOwner, dwSize, &dwSize))
735 {
736 goto fail;
737 }
738
739 if (!InitializeSecurityDescriptor(&SecDesc, SECURITY_DESCRIPTOR_REVISION))
740 {
741 goto fail;
742 }
743
744 if (!SetSecurityDescriptorOwner(&SecDesc, pOwner->Owner, FALSE))
745 {
746 goto fail;
747 }
748
749 if (!SetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION, &SecDesc))
750 {
751 goto fail;
752 }
753
754 MyFree(pOwner);
755 CloseHandle(hToken);
756
757 return ERROR_SUCCESS;
758
759 fail:;
760 dwError = GetLastError();
761
762 if (pOwner != NULL)
763 MyFree(pOwner);
764
765 if (hToken != NULL)
766 CloseHandle(hToken);
767
768 return dwError;
769 }
770
771
772 /**************************************************************************
773 * RetreiveFileSecurity [SETUPAPI.@]
774 *
775 * Retrieve the security descriptor that is associated with the given file.
776 *
777 * PARAMS
778 * lpFileName [I] Name of the file
779 *
780 * RETURNS
781 * Success: ERROR_SUCCESS
782 * Failure: other
783 */
784 DWORD WINAPI RetreiveFileSecurity(LPCWSTR lpFileName,
785 PSECURITY_DESCRIPTOR *pSecurityDescriptor)
786 {
787 PSECURITY_DESCRIPTOR SecDesc;
788 DWORD dwSize = 0x100;
789 DWORD dwError;
790
791 TRACE("%s %p\n", debugstr_w(lpFileName), pSecurityDescriptor);
792
793 SecDesc = (PSECURITY_DESCRIPTOR)MyMalloc(dwSize);
794 if (SecDesc == NULL)
795 return ERROR_NOT_ENOUGH_MEMORY;
796
797 if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION |
798 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
799 SecDesc, dwSize, &dwSize))
800 {
801 *pSecurityDescriptor = SecDesc;
802 return ERROR_SUCCESS;
803 }
804
805 dwError = GetLastError();
806 if (dwError != ERROR_INSUFFICIENT_BUFFER)
807 {
808 MyFree(SecDesc);
809 return dwError;
810 }
811
812 SecDesc = (PSECURITY_DESCRIPTOR)MyRealloc(SecDesc, dwSize);
813 if (SecDesc == NULL)
814 return ERROR_NOT_ENOUGH_MEMORY;
815
816 if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION |
817 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
818 SecDesc, dwSize, &dwSize))
819 {
820 *pSecurityDescriptor = SecDesc;
821 return ERROR_SUCCESS;
822 }
823
824 dwError = GetLastError();
825 MyFree(SecDesc);
826
827 return dwError;
828 }
829
830
831 /**************************************************************************
832 * AssertFail [SETUPAPI.@]
833 *
834 * Display an assertion message.
835 *
836 * PARAMS
837 * lpFile [I] File name
838 * uLine [I] Line number
839 * lpMessage [I] Assertion message
840 *
841 * RETURNS
842 * Nothing
843 */
844 VOID WINAPI AssertFail(LPSTR lpFile, UINT uLine, LPSTR lpMessage)
845 {
846 CHAR szModule[MAX_PATH];
847 CHAR szBuffer[2048];
848 LPSTR lpName;
849 // LPSTR lpBuffer;
850
851 TRACE("%s %u %s\n", lpFile, uLine, lpMessage);
852
853 GetModuleFileNameA(hInstance, szModule, MAX_PATH);
854 lpName = strrchr(szModule, '\\');
855 if (lpName != NULL)
856 lpName++;
857 else
858 lpName = szModule;
859
860 wsprintfA(szBuffer,
861 "Assertion failure at line %u in file %s: %s\n\nCall DebugBreak()?",
862 uLine, lpFile, lpMessage);
863
864 if (MessageBoxA(NULL, szBuffer, lpName, MB_SETFOREGROUND |
865 MB_TASKMODAL | MB_ICONERROR | MB_YESNO) == IDYES)
866 DebugBreak();
867 }
868
869
870 /**************************************************************************
871 * GetSetFileTimestamp [SETUPAPI.@]
872 *
873 * Gets or sets a files timestamp.
874 *
875 * PARAMS
876 * lpFileName [I] File name
877 * lpCreationTime [I/O] Creation time
878 * lpLastAccessTime [I/O] Last access time
879 * lpLastWriteTime [I/O] Last write time
880 * bSetFileTime [I] TRUE: Set file times
881 * FALSE: Get file times
882 *
883 * RETURNS
884 * Success: ERROR_SUCCESS
885 * Failure: other
886 */
887 DWORD WINAPI GetSetFileTimestamp(LPCWSTR lpFileName,
888 LPFILETIME lpCreationTime,
889 LPFILETIME lpLastAccessTime,
890 LPFILETIME lpLastWriteTime,
891 BOOLEAN bSetFileTime)
892 {
893 HANDLE hFile;
894 BOOLEAN bRet;
895 DWORD dwError = ERROR_SUCCESS;
896
897 TRACE("%s %p %p %p %x\n", debugstr_w(lpFileName), lpCreationTime,
898 lpLastAccessTime, lpLastWriteTime, bSetFileTime);
899
900 hFile = CreateFileW(lpFileName,
901 bSetFileTime ? GENERIC_WRITE : GENERIC_READ,
902 FILE_SHARE_READ | FILE_SHARE_WRITE,
903 NULL,
904 OPEN_EXISTING,
905 0,
906 NULL);
907
908 if (hFile == INVALID_HANDLE_VALUE)
909 return GetLastError();
910
911 if (bSetFileTime)
912 bRet = SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
913 else
914 bRet = GetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
915
916 if (bRet == FALSE)
917 dwError = GetLastError();
918
919 CloseHandle(hFile);
920
921 return dwError;
922 }
923
924
925 /**************************************************************************
926 * MyGetFileTitle [SETUPAPI.@]
927 *
928 * Returns a pointer to the last part of a fully qualified file name.
929 *
930 * PARAMS
931 * lpFileName [I] File name
932 *
933 * RETURNS
934 * Pointer to a files name.
935 */
936 LPWSTR WINAPI
937 MyGetFileTitle(LPCWSTR lpFileName)
938 {
939 LPWSTR ptr;
940 LPWSTR ret;
941 WCHAR c;
942
943 TRACE("%s\n", debugstr_w(lpFileName));
944
945 ptr = (LPWSTR)lpFileName;
946 ret = ptr;
947 while (TRUE)
948 {
949 c = *ptr;
950
951 if (c == 0)
952 break;
953
954 ptr++;
955 if (c == (WCHAR)'\\' || c == (WCHAR)'/' || c == (WCHAR)':')
956 ret = ptr;
957 }
958
959 return ret;
960 }
961
962
963 /**************************************************************************
964 * ConcatenatePaths [SETUPAPI.@]
965 *
966 * Concatenates two paths.
967 *
968 * PARAMS
969 * lpPath [I/O] Path to append path to
970 * lpAppend [I] Path to append
971 * dwBufferSize [I] Size of the path buffer
972 * lpRequiredSize [O] Required size for the concatenated path. Optional
973 *
974 * RETURNS
975 * Success: TRUE
976 * Failure: FALSE
977 */
978 BOOL WINAPI
979 ConcatenatePaths(LPWSTR lpPath,
980 LPCWSTR lpAppend,
981 DWORD dwBufferSize,
982 LPDWORD lpRequiredSize)
983 {
984 DWORD dwPathSize;
985 DWORD dwAppendSize;
986 DWORD dwTotalSize;
987 BOOL bBackslash = FALSE;
988
989 TRACE("%s %s %lu %p\n", debugstr_w(lpPath), debugstr_w(lpAppend),
990 dwBufferSize, lpRequiredSize);
991
992 dwPathSize = lstrlenW(lpPath);
993
994 /* Ignore trailing backslash */
995 if (lpPath[dwPathSize - 1] == (WCHAR)'\\')
996 dwPathSize--;
997
998 dwAppendSize = lstrlenW(lpAppend);
999
1000 /* Does the source string have a leading backslash? */
1001 if (lpAppend[0] == (WCHAR)'\\')
1002 {
1003 bBackslash = TRUE;
1004 dwAppendSize--;
1005 }
1006
1007 dwTotalSize = dwPathSize + dwAppendSize + 2;
1008 if (lpRequiredSize != NULL)
1009 *lpRequiredSize = dwTotalSize;
1010
1011 /* Append a backslash to the destination string */
1012 if (bBackslash == FALSE)
1013 {
1014 if (dwPathSize < dwBufferSize)
1015 {
1016 lpPath[dwPathSize - 1] = (WCHAR)'\\';
1017 dwPathSize++;
1018 }
1019 }
1020
1021 if (dwPathSize + dwAppendSize < dwBufferSize)
1022 {
1023 lstrcpynW(&lpPath[dwPathSize],
1024 lpAppend,
1025 dwAppendSize);
1026 }
1027
1028 if (dwBufferSize >= dwTotalSize)
1029 lpPath[dwTotalSize - 1] = 0;
1030
1031 return (dwBufferSize >= dwTotalSize);
1032 }
1033
1034
1035 /**************************************************************************
1036 * CenterWindowRelativeToParent [SETUPAPI.@]
1037 *
1038 * Centers a window relative to its parent.
1039 *
1040 * PARAMS
1041 * hwnd [I] Window to center.
1042 *
1043 * RETURNS
1044 * None
1045 */
1046 VOID WINAPI
1047 CenterWindowRelativeToParent(HWND hwnd)
1048 {
1049 HWND hwndOwner;
1050 POINT ptOrigin;
1051 RECT rcWindow;
1052 RECT rcOwner;
1053 INT nWindowWidth, nWindowHeight;
1054 INT nOwnerWidth, nOwnerHeight;
1055 INT posX, posY;
1056
1057 hwndOwner = GetWindow(hwnd, GW_OWNER);
1058 if (hwndOwner == NULL)
1059 return;
1060
1061 ptOrigin.x = 0;
1062 ptOrigin.y = 0;
1063 ClientToScreen(hwndOwner, &ptOrigin);
1064
1065 GetWindowRect(hwnd, &rcWindow);
1066 GetClientRect(hwndOwner, &rcOwner);
1067
1068 nWindowWidth = rcWindow.right - rcWindow.left;
1069 nWindowHeight = rcWindow.bottom - rcWindow.top;
1070
1071 nOwnerWidth = rcOwner.right - rcOwner.left;
1072 nOwnerHeight = rcOwner.bottom - rcOwner.top;
1073
1074 posX = ((nOwnerWidth - nWindowWidth) / 2) + ptOrigin.x;
1075 posY = ((nOwnerHeight - nWindowHeight) / 2) + ptOrigin.y;
1076
1077 MoveWindow(hwnd, posX, posY, nWindowHeight, nWindowWidth, 0);
1078 }
1079
1080
1081 /**************************************************************************
1082 * GetVersionInfoFromImage [SETUPAPI.@]
1083 *
1084 * Retrieves version information for a given file.
1085 *
1086 * PARAMS
1087 * lpFileName [I] File name
1088 * lpFileVersion [O] Pointer to the full file version
1089 * lpVersionVarSize [O] Pointer to the size of the variable version
1090 * information
1091 *
1092 * RETURNS
1093 * Success: TRUE
1094 * Failure: FALSE
1095 */
1096 BOOL WINAPI
1097 GetVersionInfoFromImage(LPWSTR lpFileName,
1098 PULARGE_INTEGER lpFileVersion,
1099 LPWORD lpVersionVarSize)
1100 {
1101 DWORD dwHandle;
1102 DWORD dwSize;
1103 LPVOID lpInfo;
1104 UINT uSize;
1105 VS_FIXEDFILEINFO *lpFixedInfo;
1106 LPWORD lpVarSize;
1107
1108 dwSize = GetFileVersionInfoSizeW(lpFileName, &dwHandle);
1109 if (dwSize == 0)
1110 return FALSE;
1111
1112 lpInfo = MyMalloc(dwSize);
1113 if (lpInfo == NULL)
1114 return FALSE;
1115
1116 if (!GetFileVersionInfoW(lpFileName, 0, dwSize, lpInfo))
1117 {
1118 MyFree(lpInfo);
1119 return FALSE;
1120 }
1121
1122 if (!VerQueryValueW(lpInfo, L"\\",
1123 (LPVOID*)&lpFixedInfo, &uSize))
1124 {
1125 MyFree(lpInfo);
1126 return FALSE;
1127 }
1128
1129 lpFileVersion->LowPart = lpFixedInfo->dwFileVersionLS;
1130 lpFileVersion->HighPart = lpFixedInfo->dwFileVersionMS;
1131
1132 *lpVersionVarSize = 0;
1133 if (!VerQueryValueW(lpInfo, L"\\VerFileInfo\\Translation",
1134 (LPVOID*)&lpVarSize, &uSize))
1135 {
1136 MyFree(lpInfo);
1137 return TRUE;
1138 }
1139
1140 if (uSize >= 4)
1141 {
1142 *lpVersionVarSize = *lpVarSize;
1143 }
1144
1145 MyFree(lpInfo);
1146
1147 return TRUE;
1148 }