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