2 * Setupapi miscellaneous functions
4 * Copyright 2005 Eric Kohl
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "setupapi_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
25 /**************************************************************************
28 * Frees an allocated memory block from the process heap.
31 * lpMem [I] pointer to memory block which will be freed
36 VOID WINAPI
MyFree(LPVOID lpMem
)
39 HeapFree(GetProcessHeap(), 0, lpMem
);
43 /**************************************************************************
44 * MyMalloc [SETUPAPI.@]
46 * Allocates memory block from the process heap.
49 * dwSize [I] size of the allocated memory block
52 * Success: pointer to allocated memory block
55 LPVOID WINAPI
MyMalloc(DWORD dwSize
)
57 TRACE("%lu\n", dwSize
);
58 return HeapAlloc(GetProcessHeap(), 0, dwSize
);
62 /**************************************************************************
63 * MyRealloc [SETUPAPI.@]
65 * Changes the size of an allocated memory block or allocates a memory
66 * block from the process heap.
69 * lpSrc [I] pointer to memory block which will be resized
70 * dwSize [I] new size of the memory block
73 * Success: pointer to the resized memory block
77 * If lpSrc is a NULL-pointer, then MyRealloc allocates a memory
78 * block like MyMalloc.
80 LPVOID WINAPI
MyRealloc(LPVOID lpSrc
, DWORD dwSize
)
82 TRACE("%p %lu\n", lpSrc
, dwSize
);
85 return HeapAlloc(GetProcessHeap(), 0, dwSize
);
87 return HeapReAlloc(GetProcessHeap(), 0, lpSrc
, dwSize
);
91 /**************************************************************************
92 * DuplicateString [SETUPAPI.@]
94 * Duplicates a unicode string.
97 * lpSrc [I] pointer to the unicode string that will be duplicated
100 * Success: pointer to the duplicated unicode string
104 * Call MyFree() to release the duplicated string.
106 LPWSTR WINAPI
DuplicateString(LPCWSTR lpSrc
)
110 TRACE("%s\n", debugstr_w(lpSrc
));
112 lpDst
= MyMalloc((lstrlenW(lpSrc
) + 1) * sizeof(WCHAR
));
116 strcpyW(lpDst
, lpSrc
);
122 /**************************************************************************
123 * QueryRegistryValue [SETUPAPI.@]
125 * Retrieves value data from the registry and allocates memory for the
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
136 * Success: ERROR_SUCCESS
140 * Use MyFree to release the lpData buffer.
142 LONG WINAPI
QueryRegistryValue(HKEY hKey
,
150 TRACE("%p %s %p %p %p\n",
151 hKey
, debugstr_w(lpValueName
), lpData
, lpType
, lpcbData
);
153 /* Get required buffer size */
155 lError
= RegQueryValueExW(hKey
, lpValueName
, 0, lpType
, NULL
, lpcbData
);
156 if (lError
!= ERROR_SUCCESS
)
159 /* Allocate buffer */
160 *lpData
= MyMalloc(*lpcbData
);
162 return ERROR_NOT_ENOUGH_MEMORY
;
164 /* Query registry value */
165 lError
= RegQueryValueExW(hKey
, lpValueName
, 0, lpType
, *lpData
, lpcbData
);
166 if (lError
!= ERROR_SUCCESS
)
173 /**************************************************************************
174 * IsUserAdmin [SETUPAPI.@]
176 * Checks whether the current user is a member of the Administrators group.
185 BOOL WINAPI
IsUserAdmin(VOID
)
187 SID_IDENTIFIER_AUTHORITY Authority
= {SECURITY_NT_AUTHORITY
};
190 PTOKEN_GROUPS lpGroups
;
193 BOOL bResult
= FALSE
;
197 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
202 if (!GetTokenInformation(hToken
, TokenGroups
, NULL
, 0, &dwSize
))
204 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
211 lpGroups
= MyMalloc(dwSize
);
212 if (lpGroups
== NULL
)
218 if (!GetTokenInformation(hToken
, TokenGroups
, lpGroups
, dwSize
, &dwSize
))
227 if (!AllocateAndInitializeSid(&Authority
, 2, SECURITY_BUILTIN_DOMAIN_RID
,
228 DOMAIN_ALIAS_RID_ADMINS
, 0, 0, 0, 0, 0, 0,
235 for (i
= 0; i
< lpGroups
->GroupCount
; i
++)
237 if (EqualSid(lpSid
, lpGroups
->Groups
[i
].Sid
))
251 /**************************************************************************
252 * MultiByteToUnicode [SETUPAPI.@]
254 * Converts a multi-byte string to a Unicode string.
257 * lpMultiByteStr [I] Multi-byte string to be converted
258 * uCodePage [I] Code page
261 * Success: pointer to the converted Unicode string
265 * Use MyFree to release the returned Unicode string.
267 LPWSTR WINAPI
MultiByteToUnicode(LPCSTR lpMultiByteStr
, UINT uCodePage
)
272 TRACE("%s %d\n", debugstr_a(lpMultiByteStr
), uCodePage
);
274 nLength
= MultiByteToWideChar(uCodePage
, 0, lpMultiByteStr
,
279 lpUnicodeStr
= MyMalloc(nLength
* sizeof(WCHAR
));
280 if (lpUnicodeStr
== NULL
)
282 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
286 if (!MultiByteToWideChar(uCodePage
, 0, lpMultiByteStr
,
287 nLength
, lpUnicodeStr
, nLength
))
289 MyFree(lpUnicodeStr
);
297 /**************************************************************************
298 * UnicodeToMultiByte [SETUPAPI.@]
300 * Converts a Unicode string to a multi-byte string.
303 * lpUnicodeStr [I] Unicode string to be converted
304 * uCodePage [I] Code page
307 * Success: pointer to the converted multi-byte string
311 * Use MyFree to release the returned multi-byte string.
313 LPSTR WINAPI
UnicodeToMultiByte(LPCWSTR lpUnicodeStr
, UINT uCodePage
)
315 LPSTR lpMultiByteStr
;
318 TRACE("%s %d\n", debugstr_w(lpUnicodeStr
), uCodePage
);
320 nLength
= WideCharToMultiByte(uCodePage
, 0, lpUnicodeStr
, -1,
321 NULL
, 0, NULL
, NULL
);
325 lpMultiByteStr
= MyMalloc(nLength
);
326 if (lpMultiByteStr
== NULL
)
329 if (!WideCharToMultiByte(uCodePage
, 0, lpUnicodeStr
, -1,
330 lpMultiByteStr
, nLength
, NULL
, NULL
))
332 MyFree(lpMultiByteStr
);
336 return lpMultiByteStr
;
340 /**************************************************************************
341 * DoesUserHavePrivilege [SETUPAPI.@]
343 * Check whether the current user has got a given privilege.
346 * lpPrivilegeName [I] Name of the privilege to be checked
352 BOOL WINAPI
DoesUserHavePrivilege(LPCWSTR lpPrivilegeName
)
356 PTOKEN_PRIVILEGES lpPrivileges
;
359 BOOL bResult
= FALSE
;
361 TRACE("%s\n", debugstr_w(lpPrivilegeName
));
363 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
366 if (!GetTokenInformation(hToken
, TokenPrivileges
, NULL
, 0, &dwSize
))
368 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
375 lpPrivileges
= MyMalloc(dwSize
);
376 if (lpPrivileges
== NULL
)
382 if (!GetTokenInformation(hToken
, TokenPrivileges
, lpPrivileges
, dwSize
, &dwSize
))
384 MyFree(lpPrivileges
);
391 if (!LookupPrivilegeValueW(NULL
, lpPrivilegeName
, &PrivilegeLuid
))
393 MyFree(lpPrivileges
);
397 for (i
= 0; i
< lpPrivileges
->PrivilegeCount
; i
++)
399 if (lpPrivileges
->Privileges
[i
].Luid
.HighPart
== PrivilegeLuid
.HighPart
&&
400 lpPrivileges
->Privileges
[i
].Luid
.LowPart
== PrivilegeLuid
.LowPart
)
406 MyFree(lpPrivileges
);
412 /**************************************************************************
413 * EnablePrivilege [SETUPAPI.@]
415 * Enables or disables one of the current users privileges.
418 * lpPrivilegeName [I] Name of the privilege to be changed
419 * bEnable [I] TRUE: Enables the privilege
420 * FALSE: Disables the privilege
426 BOOL WINAPI
EnablePrivilege(LPCWSTR lpPrivilegeName
, BOOL bEnable
)
428 TOKEN_PRIVILEGES Privileges
;
432 TRACE("%s %s\n", debugstr_w(lpPrivilegeName
), bEnable
? "TRUE" : "FALSE");
434 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
437 Privileges
.PrivilegeCount
= 1;
438 Privileges
.Privileges
[0].Attributes
= (bEnable
) ? SE_PRIVILEGE_ENABLED
: 0;
440 if (!LookupPrivilegeValueW(NULL
, lpPrivilegeName
,
441 &Privileges
.Privileges
[0].Luid
))
447 bResult
= AdjustTokenPrivileges(hToken
, FALSE
, &Privileges
, 0, NULL
, NULL
);
455 /**************************************************************************
456 * DelayedMove [SETUPAPI.@]
458 * Moves a file upon the next reboot.
461 * lpExistingFileName [I] Current file name
462 * lpNewFileName [I] New file name
468 BOOL WINAPI
DelayedMove(LPCWSTR lpExistingFileName
, LPCWSTR lpNewFileName
)
470 return MoveFileExW(lpExistingFileName
, lpNewFileName
,
471 MOVEFILE_REPLACE_EXISTING
| MOVEFILE_DELAY_UNTIL_REBOOT
);
475 /**************************************************************************
476 * FileExists [SETUPAPI.@]
478 * Checks whether a file exists.
481 * lpFileName [I] Name of the file to check
482 * lpNewFileName [O] Optional information about the existing file
488 BOOL WINAPI
FileExists(LPCWSTR lpFileName
, LPWIN32_FIND_DATAW lpFileFindData
)
490 WIN32_FIND_DATAW FindData
;
495 uErrorMode
= SetErrorMode(SEM_FAILCRITICALERRORS
);
497 hFind
= FindFirstFileW(lpFileName
, &FindData
);
498 if (hFind
== INVALID_HANDLE_VALUE
)
500 dwError
= GetLastError();
501 SetErrorMode(uErrorMode
);
502 SetLastError(dwError
);
509 memcpy(lpFileFindData
, &FindData
, sizeof(WIN32_FIND_DATAW
));
511 SetErrorMode(uErrorMode
);
517 /**************************************************************************
518 * CaptureStringArg [SETUPAPI.@]
520 * Captures a UNICODE string.
523 * lpSrc [I] UNICODE string to be captured
524 * lpDst [O] Pointer to the captured UNICODE string
527 * Success: ERROR_SUCCESS
528 * Failure: ERROR_INVALID_PARAMETER
531 * Call MyFree to release the captured UNICODE string.
533 DWORD WINAPI
CaptureStringArg(LPCWSTR pSrc
, LPWSTR
*pDst
)
536 return ERROR_INVALID_PARAMETER
;
538 *pDst
= DuplicateString(pSrc
);
540 return ERROR_SUCCESS
;
544 /**************************************************************************
545 * CaptureAndConvertAnsiArg [SETUPAPI.@]
547 * Captures an ANSI string and converts it to a UNICODE string.
550 * lpSrc [I] ANSI string to be captured
551 * lpDst [O] Pointer to the captured UNICODE string
554 * Success: ERROR_SUCCESS
555 * Failure: ERROR_INVALID_PARAMETER
558 * Call MyFree to release the captured UNICODE string.
560 DWORD WINAPI
CaptureAndConvertAnsiArg(LPCSTR pSrc
, LPWSTR
*pDst
)
563 return ERROR_INVALID_PARAMETER
;
565 *pDst
= MultiByteToUnicode(pSrc
, CP_ACP
);
567 return ERROR_SUCCESS
;
571 /**************************************************************************
572 * OpenAndMapFileForRead [SETUPAPI.@]
574 * Open and map a file to a buffer.
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
584 * Success: ERROR_SUCCESS
588 * Call UnmapAndCloseFile to release the file.
590 DWORD WINAPI
OpenAndMapFileForRead(LPCWSTR lpFileName
,
598 TRACE("%s %p %p %p %p\n",
599 debugstr_w(lpFileName
), lpSize
, lpFile
, lpMapping
, lpBuffer
);
601 *lpFile
= CreateFileW(lpFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
602 OPEN_EXISTING
, 0, NULL
);
603 if (*lpFile
== INVALID_HANDLE_VALUE
)
604 return GetLastError();
606 *lpSize
= GetFileSize(*lpFile
, NULL
);
607 if (*lpSize
== INVALID_FILE_SIZE
)
609 dwError
= GetLastError();
610 CloseHandle(*lpFile
);
614 *lpMapping
= CreateFileMappingW(*lpFile
, NULL
, PAGE_READONLY
, 0,
616 if (*lpMapping
== NULL
)
618 dwError
= GetLastError();
619 CloseHandle(*lpFile
);
623 *lpBuffer
= MapViewOfFile(*lpMapping
, FILE_MAP_READ
, 0, 0, *lpSize
);
624 if (*lpBuffer
== NULL
)
626 dwError
= GetLastError();
627 CloseHandle(*lpMapping
);
628 CloseHandle(*lpFile
);
632 return ERROR_SUCCESS
;
636 /**************************************************************************
637 * UnmapAndCloseFile [SETUPAPI.@]
639 * Unmap and close a mapped file.
642 * hFile [I] Handle to the file
643 * hMapping [I] Handle to the file mapping
644 * lpBuffer [I] Pointer to the file buffer
650 BOOL WINAPI
UnmapAndCloseFile(HANDLE hFile
, HANDLE hMapping
, LPVOID lpBuffer
)
653 hFile
, hMapping
, lpBuffer
);
655 if (!UnmapViewOfFile(lpBuffer
))
658 if (!CloseHandle(hMapping
))
661 if (!CloseHandle(hFile
))
668 /**************************************************************************
669 * StampFileSecurity [SETUPAPI.@]
671 * Assign a new security descriptor to the given file.
674 * lpFileName [I] Name of the file
675 * pSecurityDescriptor [I] New security descriptor
678 * Success: ERROR_SUCCESS
681 DWORD WINAPI
StampFileSecurity(LPCWSTR lpFileName
, PSECURITY_DESCRIPTOR pSecurityDescriptor
)
683 TRACE("%s %p\n", debugstr_w(lpFileName
), pSecurityDescriptor
);
685 if (!SetFileSecurityW(lpFileName
, OWNER_SECURITY_INFORMATION
|
686 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
687 pSecurityDescriptor
))
688 return GetLastError();
690 return ERROR_SUCCESS
;
694 /**************************************************************************
695 * TakeOwnershipOfFile [SETUPAPI.@]
697 * Takes the ownership of the given file.
700 * lpFileName [I] Name of the file
703 * Success: ERROR_SUCCESS
706 DWORD WINAPI
TakeOwnershipOfFile(LPCWSTR lpFileName
)
708 SECURITY_DESCRIPTOR SecDesc
;
709 HANDLE hToken
= NULL
;
710 PTOKEN_OWNER pOwner
= NULL
;
714 TRACE("%s\n", debugstr_w(lpFileName
));
716 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
717 return GetLastError();
719 if (!GetTokenInformation(hToken
, TokenOwner
, NULL
, 0, &dwSize
))
724 pOwner
= (PTOKEN_OWNER
)MyMalloc(dwSize
);
728 return ERROR_NOT_ENOUGH_MEMORY
;
731 if (!GetTokenInformation(hToken
, TokenOwner
, pOwner
, dwSize
, &dwSize
))
736 if (!InitializeSecurityDescriptor(&SecDesc
, SECURITY_DESCRIPTOR_REVISION
))
741 if (!SetSecurityDescriptorOwner(&SecDesc
, pOwner
->Owner
, FALSE
))
746 if (!SetFileSecurityW(lpFileName
, OWNER_SECURITY_INFORMATION
, &SecDesc
))
754 return ERROR_SUCCESS
;
757 dwError
= GetLastError();
769 /**************************************************************************
770 * RetreiveFileSecurity [SETUPAPI.@]
772 * Retrieve the security descriptor that is associated with the given file.
775 * lpFileName [I] Name of the file
778 * Success: ERROR_SUCCESS
781 DWORD WINAPI
RetreiveFileSecurity(LPCWSTR lpFileName
,
782 PSECURITY_DESCRIPTOR
*pSecurityDescriptor
)
784 PSECURITY_DESCRIPTOR SecDesc
;
785 DWORD dwSize
= 0x100;
788 TRACE("%s %p\n", debugstr_w(lpFileName
), pSecurityDescriptor
);
790 SecDesc
= (PSECURITY_DESCRIPTOR
)MyMalloc(dwSize
);
792 return ERROR_NOT_ENOUGH_MEMORY
;
794 if (GetFileSecurityW(lpFileName
, OWNER_SECURITY_INFORMATION
|
795 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
796 SecDesc
, dwSize
, &dwSize
))
798 *pSecurityDescriptor
= SecDesc
;
799 return ERROR_SUCCESS
;
802 dwError
= GetLastError();
803 if (dwError
!= ERROR_INSUFFICIENT_BUFFER
)
809 SecDesc
= (PSECURITY_DESCRIPTOR
)MyRealloc(SecDesc
, dwSize
);
811 return ERROR_NOT_ENOUGH_MEMORY
;
813 if (GetFileSecurityW(lpFileName
, OWNER_SECURITY_INFORMATION
|
814 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
815 SecDesc
, dwSize
, &dwSize
))
817 *pSecurityDescriptor
= SecDesc
;
818 return ERROR_SUCCESS
;
821 dwError
= GetLastError();
828 /**************************************************************************
829 * AssertFail [SETUPAPI.@]
831 * Display an assertion message.
834 * lpFile [I] File name
835 * uLine [I] Line number
836 * lpMessage [I] Assertion message
841 VOID WINAPI
AssertFail(LPSTR lpFile
, UINT uLine
, LPSTR lpMessage
)
843 CHAR szModule
[MAX_PATH
];
848 TRACE("%s %u %s\n", lpFile
, uLine
, lpMessage
);
850 GetModuleFileNameA(hInstance
, szModule
, MAX_PATH
);
851 lpName
= strrchr(szModule
, '\\');
858 "Assertion failure at line %u in file %s: %s\n\nCall DebugBreak()?",
859 uLine
, lpFile
, lpMessage
);
861 if (MessageBoxA(NULL
, szBuffer
, lpName
, MB_SETFOREGROUND
|
862 MB_TASKMODAL
| MB_ICONERROR
| MB_YESNO
) == IDYES
)
867 /**************************************************************************
868 * GetSetFileTimestamp [SETUPAPI.@]
870 * Gets or sets a files timestamp.
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
881 * Success: ERROR_SUCCESS
884 DWORD WINAPI
GetSetFileTimestamp(LPCWSTR lpFileName
,
885 LPFILETIME lpCreationTime
,
886 LPFILETIME lpLastAccessTime
,
887 LPFILETIME lpLastWriteTime
,
888 BOOLEAN bSetFileTime
)
892 DWORD dwError
= ERROR_SUCCESS
;
894 TRACE("%s %p %p %p %x\n", debugstr_w(lpFileName
), lpCreationTime
,
895 lpLastAccessTime
, lpLastWriteTime
, bSetFileTime
);
897 hFile
= CreateFileW(lpFileName
,
898 bSetFileTime
? GENERIC_WRITE
: GENERIC_READ
,
899 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
905 if (hFile
== INVALID_HANDLE_VALUE
)
906 return GetLastError();
909 bRet
= SetFileTime(hFile
, lpCreationTime
, lpLastAccessTime
, lpLastWriteTime
);
911 bRet
= GetFileTime(hFile
, lpCreationTime
, lpLastAccessTime
, lpLastWriteTime
);
914 dwError
= GetLastError();
922 /**************************************************************************
923 * MyGetFileTitle [SETUPAPI.@]
925 * Returns a pointer to the last part of a fully qualified file name.
928 * lpFileName [I] File name
931 * Pointer to a files name.
934 MyGetFileTitle(LPCWSTR lpFileName
)
940 TRACE("%s\n", debugstr_w(lpFileName
));
942 ptr
= (LPWSTR
)lpFileName
;
952 if (c
== (WCHAR
)'\\' || c
== (WCHAR
)'/' || c
== (WCHAR
)':')
960 /**************************************************************************
961 * ConcatenatePaths [SETUPAPI.@]
963 * Concatenates two paths.
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
976 ConcatenatePaths(LPWSTR lpPath
,
979 LPDWORD lpRequiredSize
)
984 BOOL bBackslash
= FALSE
;
986 TRACE("%s %s %lu %p\n", debugstr_w(lpPath
), debugstr_w(lpAppend
),
987 dwBufferSize
, lpRequiredSize
);
989 dwPathSize
= lstrlenW(lpPath
);
991 /* Ignore trailing backslash */
992 if (lpPath
[dwPathSize
- 1] == (WCHAR
)'\\')
995 dwAppendSize
= lstrlenW(lpAppend
);
997 /* Does the source string have a leading backslash? */
998 if (lpAppend
[0] == (WCHAR
)'\\')
1004 dwTotalSize
= dwPathSize
+ dwAppendSize
+ 2;
1005 if (lpRequiredSize
!= NULL
)
1006 *lpRequiredSize
= dwTotalSize
;
1008 /* Append a backslash to the destination string */
1009 if (bBackslash
== FALSE
)
1011 if (dwPathSize
< dwBufferSize
)
1013 lpPath
[dwPathSize
- 1] = (WCHAR
)'\\';
1018 if (dwPathSize
+ dwAppendSize
< dwBufferSize
)
1020 lstrcpynW(&lpPath
[dwPathSize
],
1025 if (dwBufferSize
>= dwTotalSize
)
1026 lpPath
[dwTotalSize
- 1] = 0;
1028 return (dwBufferSize
>= dwTotalSize
);
1032 /**************************************************************************
1033 * CenterWindowRelativeToParent [SETUPAPI.@]
1035 * Centers a window relative to its parent.
1038 * hwnd [I] Window to center.
1044 CenterWindowRelativeToParent(HWND hwnd
)
1050 INT nWindowWidth
, nWindowHeight
;
1051 INT nOwnerWidth
, nOwnerHeight
;
1054 hwndOwner
= GetWindow(hwnd
, GW_OWNER
);
1055 if (hwndOwner
== NULL
)
1060 ClientToScreen(hwndOwner
, &ptOrigin
);
1062 GetWindowRect(hwnd
, &rcWindow
);
1063 GetClientRect(hwndOwner
, &rcOwner
);
1065 nWindowWidth
= rcWindow
.right
- rcWindow
.left
;
1066 nWindowHeight
= rcWindow
.bottom
- rcWindow
.top
;
1068 nOwnerWidth
= rcOwner
.right
- rcOwner
.left
;
1069 nOwnerHeight
= rcOwner
.bottom
- rcOwner
.top
;
1071 posX
= ((nOwnerWidth
- nWindowWidth
) / 2) + ptOrigin
.x
;
1072 posY
= ((nOwnerHeight
- nWindowHeight
) / 2) + ptOrigin
.y
;
1074 MoveWindow(hwnd
, posX
, posY
, nWindowHeight
, nWindowWidth
, 0);
1078 /**************************************************************************
1079 * GetVersionInfoFromImage [SETUPAPI.@]
1081 * Retrieves version information for a given file.
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
1094 GetVersionInfoFromImage(LPWSTR lpFileName
,
1095 PULARGE_INTEGER lpFileVersion
,
1096 LPWORD lpVersionVarSize
)
1102 VS_FIXEDFILEINFO
*lpFixedInfo
;
1105 dwSize
= GetFileVersionInfoSizeW(lpFileName
, &dwHandle
);
1109 lpInfo
= MyMalloc(dwSize
);
1113 if (!GetFileVersionInfoW(lpFileName
, 0, dwSize
, lpInfo
))
1119 if (!VerQueryValueW(lpInfo
, L
"\\",
1120 (LPVOID
*)&lpFixedInfo
, &uSize
))
1126 lpFileVersion
->LowPart
= lpFixedInfo
->dwFileVersionLS
;
1127 lpFileVersion
->HighPart
= lpFixedInfo
->dwFileVersionMS
;
1129 *lpVersionVarSize
= 0;
1130 if (!VerQueryValueW(lpInfo
, L
"\\VerFileInfo\\Translation",
1131 (LPVOID
*)&lpVarSize
, &uSize
))
1139 *lpVersionVarSize
= *lpVarSize
;