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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
)
283 if (!MultiByteToWideChar(uCodePage
, 0, lpMultiByteStr
,
284 nLength
, lpUnicodeStr
, nLength
))
286 MyFree(lpUnicodeStr
);
294 /**************************************************************************
295 * UnicodeToMultiByte [SETUPAPI.@]
297 * Converts a Unicode string to a multi-byte string.
300 * lpUnicodeStr [I] Unicode string to be converted
301 * uCodePage [I] Code page
304 * Success: pointer to the converted multi-byte string
308 * Use MyFree to release the returned multi-byte string.
310 LPSTR WINAPI
UnicodeToMultiByte(LPCWSTR lpUnicodeStr
, UINT uCodePage
)
312 LPSTR lpMultiByteStr
;
315 TRACE("%s %d\n", debugstr_w(lpUnicodeStr
), uCodePage
);
317 nLength
= WideCharToMultiByte(uCodePage
, 0, lpUnicodeStr
, -1,
318 NULL
, 0, NULL
, NULL
);
322 lpMultiByteStr
= MyMalloc(nLength
);
323 if (lpMultiByteStr
== NULL
)
326 if (!WideCharToMultiByte(uCodePage
, 0, lpUnicodeStr
, -1,
327 lpMultiByteStr
, nLength
, NULL
, NULL
))
329 MyFree(lpMultiByteStr
);
333 return lpMultiByteStr
;
337 /**************************************************************************
338 * DoesUserHavePrivilege [SETUPAPI.@]
340 * Check whether the current user has got a given privilege.
343 * lpPrivilegeName [I] Name of the privilege to be checked
349 BOOL WINAPI
DoesUserHavePrivilege(LPCWSTR lpPrivilegeName
)
353 PTOKEN_PRIVILEGES lpPrivileges
;
356 BOOL bResult
= FALSE
;
358 TRACE("%s\n", debugstr_w(lpPrivilegeName
));
360 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
363 if (!GetTokenInformation(hToken
, TokenPrivileges
, NULL
, 0, &dwSize
))
365 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
372 lpPrivileges
= MyMalloc(dwSize
);
373 if (lpPrivileges
== NULL
)
379 if (!GetTokenInformation(hToken
, TokenPrivileges
, lpPrivileges
, dwSize
, &dwSize
))
381 MyFree(lpPrivileges
);
388 if (!LookupPrivilegeValueW(NULL
, lpPrivilegeName
, &PrivilegeLuid
))
390 MyFree(lpPrivileges
);
394 for (i
= 0; i
< lpPrivileges
->PrivilegeCount
; i
++)
396 if (lpPrivileges
->Privileges
[i
].Luid
.HighPart
== PrivilegeLuid
.HighPart
&&
397 lpPrivileges
->Privileges
[i
].Luid
.LowPart
== PrivilegeLuid
.LowPart
)
403 MyFree(lpPrivileges
);
409 /**************************************************************************
410 * EnablePrivilege [SETUPAPI.@]
412 * Enables or disables one of the current users privileges.
415 * lpPrivilegeName [I] Name of the privilege to be changed
416 * bEnable [I] TRUE: Enables the privilege
417 * FALSE: Disables the privilege
423 BOOL WINAPI
EnablePrivilege(LPCWSTR lpPrivilegeName
, BOOL bEnable
)
425 TOKEN_PRIVILEGES Privileges
;
429 TRACE("%s %s\n", debugstr_w(lpPrivilegeName
), bEnable
? "TRUE" : "FALSE");
431 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
434 Privileges
.PrivilegeCount
= 1;
435 Privileges
.Privileges
[0].Attributes
= (bEnable
) ? SE_PRIVILEGE_ENABLED
: 0;
437 if (!LookupPrivilegeValueW(NULL
, lpPrivilegeName
,
438 &Privileges
.Privileges
[0].Luid
))
444 bResult
= AdjustTokenPrivileges(hToken
, FALSE
, &Privileges
, 0, NULL
, NULL
);
452 /**************************************************************************
453 * DelayedMove [SETUPAPI.@]
455 * Moves a file upon the next reboot.
458 * lpExistingFileName [I] Current file name
459 * lpNewFileName [I] New file name
465 BOOL WINAPI
DelayedMove(LPCWSTR lpExistingFileName
, LPCWSTR lpNewFileName
)
467 if (OsVersionInfo
.dwPlatformId
!= VER_PLATFORM_WIN32_NT
)
469 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
473 return MoveFileExW(lpExistingFileName
, lpNewFileName
,
474 MOVEFILE_REPLACE_EXISTING
| MOVEFILE_DELAY_UNTIL_REBOOT
);
478 /**************************************************************************
479 * FileExists [SETUPAPI.@]
481 * Checks whether a file exists.
484 * lpFileName [I] Name of the file to check
485 * lpNewFileName [O] Optional information about the existing file
491 BOOL WINAPI
FileExists(LPCWSTR lpFileName
, LPWIN32_FIND_DATAW lpFileFindData
)
493 WIN32_FIND_DATAW FindData
;
498 uErrorMode
= SetErrorMode(SEM_FAILCRITICALERRORS
);
500 hFind
= FindFirstFileW(lpFileName
, &FindData
);
501 if (hFind
== INVALID_HANDLE_VALUE
)
503 dwError
= GetLastError();
504 SetErrorMode(uErrorMode
);
505 SetLastError(dwError
);
512 memcpy(lpFileFindData
, &FindData
, sizeof(WIN32_FIND_DATAW
));
514 SetErrorMode(uErrorMode
);
520 /**************************************************************************
521 * CaptureStringArg [SETUPAPI.@]
523 * Captures a UNICODE string.
526 * lpSrc [I] UNICODE string to be captured
527 * lpDst [O] Pointer to the captured UNICODE string
530 * Success: ERROR_SUCCESS
531 * Failure: ERROR_INVALID_PARAMETER
534 * Call MyFree to release the captured UNICODE string.
536 DWORD WINAPI
CaptureStringArg(LPCWSTR pSrc
, LPWSTR
*pDst
)
539 return ERROR_INVALID_PARAMETER
;
541 *pDst
= DuplicateString(pSrc
);
543 return ERROR_SUCCESS
;
547 /**************************************************************************
548 * CaptureAndConvertAnsiArg [SETUPAPI.@]
550 * Captures an ANSI string and converts it to a UNICODE string.
553 * lpSrc [I] ANSI string to be captured
554 * lpDst [O] Pointer to the captured UNICODE string
557 * Success: ERROR_SUCCESS
558 * Failure: ERROR_INVALID_PARAMETER
561 * Call MyFree to release the captured UNICODE string.
563 DWORD WINAPI
CaptureAndConvertAnsiArg(LPCSTR pSrc
, LPWSTR
*pDst
)
566 return ERROR_INVALID_PARAMETER
;
568 *pDst
= MultiByteToUnicode(pSrc
, CP_ACP
);
570 return ERROR_SUCCESS
;
574 /**************************************************************************
575 * OpenAndMapFileForRead [SETUPAPI.@]
577 * Open and map a file to a buffer.
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
587 * Success: ERROR_SUCCESS
591 * Call UnmapAndCloseFile to release the file.
593 DWORD WINAPI
OpenAndMapFileForRead(LPCWSTR lpFileName
,
601 TRACE("%s %p %p %p %p\n",
602 debugstr_w(lpFileName
), lpSize
, lpFile
, lpMapping
, lpBuffer
);
604 *lpFile
= CreateFileW(lpFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
605 OPEN_EXISTING
, 0, NULL
);
606 if (*lpFile
== INVALID_HANDLE_VALUE
)
607 return GetLastError();
609 *lpSize
= GetFileSize(*lpFile
, NULL
);
610 if (*lpSize
== INVALID_FILE_SIZE
)
612 dwError
= GetLastError();
613 CloseHandle(*lpFile
);
617 *lpMapping
= CreateFileMappingW(*lpFile
, NULL
, PAGE_READONLY
, 0,
619 if (*lpMapping
== NULL
)
621 dwError
= GetLastError();
622 CloseHandle(*lpFile
);
626 *lpBuffer
= MapViewOfFile(*lpMapping
, FILE_MAP_READ
, 0, 0, *lpSize
);
627 if (*lpBuffer
== NULL
)
629 dwError
= GetLastError();
630 CloseHandle(*lpMapping
);
631 CloseHandle(*lpFile
);
635 return ERROR_SUCCESS
;
639 /**************************************************************************
640 * UnmapAndCloseFile [SETUPAPI.@]
642 * Unmap and close a mapped file.
645 * hFile [I] Handle to the file
646 * hMapping [I] Handle to the file mapping
647 * lpBuffer [I] Pointer to the file buffer
653 BOOL WINAPI
UnmapAndCloseFile(HANDLE hFile
, HANDLE hMapping
, LPVOID lpBuffer
)
656 hFile
, hMapping
, lpBuffer
);
658 if (!UnmapViewOfFile(lpBuffer
))
661 if (!CloseHandle(hMapping
))
664 if (!CloseHandle(hFile
))
671 /**************************************************************************
672 * StampFileSecurity [SETUPAPI.@]
674 * Assign a new security descriptor to the given file.
677 * lpFileName [I] Name of the file
678 * pSecurityDescriptor [I] New security descriptor
681 * Success: ERROR_SUCCESS
684 DWORD WINAPI
StampFileSecurity(LPCWSTR lpFileName
, PSECURITY_DESCRIPTOR pSecurityDescriptor
)
686 TRACE("%s %p\n", debugstr_w(lpFileName
), pSecurityDescriptor
);
688 if (!SetFileSecurityW(lpFileName
, OWNER_SECURITY_INFORMATION
|
689 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
690 pSecurityDescriptor
))
691 return GetLastError();
693 return ERROR_SUCCESS
;
697 /**************************************************************************
698 * TakeOwnershipOfFile [SETUPAPI.@]
700 * Takes the ownership of the given file.
703 * lpFileName [I] Name of the file
706 * Success: ERROR_SUCCESS
709 DWORD WINAPI
TakeOwnershipOfFile(LPCWSTR lpFileName
)
711 SECURITY_DESCRIPTOR SecDesc
;
712 HANDLE hToken
= NULL
;
713 PTOKEN_OWNER pOwner
= NULL
;
717 TRACE("%s\n", debugstr_w(lpFileName
));
719 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
720 return GetLastError();
722 if (!GetTokenInformation(hToken
, TokenOwner
, NULL
, 0, &dwSize
))
727 pOwner
= (PTOKEN_OWNER
)MyMalloc(dwSize
);
731 return ERROR_NOT_ENOUGH_MEMORY
;
734 if (!GetTokenInformation(hToken
, TokenOwner
, pOwner
, dwSize
, &dwSize
))
739 if (!InitializeSecurityDescriptor(&SecDesc
, SECURITY_DESCRIPTOR_REVISION
))
744 if (!SetSecurityDescriptorOwner(&SecDesc
, pOwner
->Owner
, FALSE
))
749 if (!SetFileSecurityW(lpFileName
, OWNER_SECURITY_INFORMATION
, &SecDesc
))
757 return ERROR_SUCCESS
;
760 dwError
= GetLastError();
772 /**************************************************************************
773 * RetreiveFileSecurity [SETUPAPI.@]
775 * Retrieve the security descriptor that is associated with the given file.
778 * lpFileName [I] Name of the file
781 * Success: ERROR_SUCCESS
784 DWORD WINAPI
RetreiveFileSecurity(LPCWSTR lpFileName
,
785 PSECURITY_DESCRIPTOR
*pSecurityDescriptor
)
787 PSECURITY_DESCRIPTOR SecDesc
;
788 DWORD dwSize
= 0x100;
791 TRACE("%s %p\n", debugstr_w(lpFileName
), pSecurityDescriptor
);
793 SecDesc
= (PSECURITY_DESCRIPTOR
)MyMalloc(dwSize
);
795 return ERROR_NOT_ENOUGH_MEMORY
;
797 if (GetFileSecurityW(lpFileName
, OWNER_SECURITY_INFORMATION
|
798 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
799 SecDesc
, dwSize
, &dwSize
))
801 *pSecurityDescriptor
= SecDesc
;
802 return ERROR_SUCCESS
;
805 dwError
= GetLastError();
806 if (dwError
!= ERROR_INSUFFICIENT_BUFFER
)
812 SecDesc
= (PSECURITY_DESCRIPTOR
)MyRealloc(SecDesc
, dwSize
);
814 return ERROR_NOT_ENOUGH_MEMORY
;
816 if (GetFileSecurityW(lpFileName
, OWNER_SECURITY_INFORMATION
|
817 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
818 SecDesc
, dwSize
, &dwSize
))
820 *pSecurityDescriptor
= SecDesc
;
821 return ERROR_SUCCESS
;
824 dwError
= GetLastError();
831 /**************************************************************************
832 * AssertFail [SETUPAPI.@]
834 * Display an assertion message.
837 * lpFile [I] File name
838 * uLine [I] Line number
839 * lpMessage [I] Assertion message
844 VOID WINAPI
AssertFail(LPSTR lpFile
, UINT uLine
, LPSTR lpMessage
)
846 CHAR szModule
[MAX_PATH
];
851 TRACE("%s %u %s\n", lpFile
, uLine
, lpMessage
);
853 GetModuleFileNameA(hInstance
, szModule
, MAX_PATH
);
854 lpName
= strrchr(szModule
, '\\');
861 "Assertion failure at line %u in file %s: %s\n\nCall DebugBreak()?",
862 uLine
, lpFile
, lpMessage
);
864 if (MessageBoxA(NULL
, szBuffer
, lpName
, MB_SETFOREGROUND
|
865 MB_TASKMODAL
| MB_ICONERROR
| MB_YESNO
) == IDYES
)
870 /**************************************************************************
871 * GetSetFileTimestamp [SETUPAPI.@]
873 * Gets or sets a files timestamp.
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
884 * Success: ERROR_SUCCESS
887 DWORD WINAPI
GetSetFileTimestamp(LPCWSTR lpFileName
,
888 LPFILETIME lpCreationTime
,
889 LPFILETIME lpLastAccessTime
,
890 LPFILETIME lpLastWriteTime
,
891 BOOLEAN bSetFileTime
)
895 DWORD dwError
= ERROR_SUCCESS
;
897 TRACE("%s %p %p %p %x\n", debugstr_w(lpFileName
), lpCreationTime
,
898 lpLastAccessTime
, lpLastWriteTime
, bSetFileTime
);
900 hFile
= CreateFileW(lpFileName
,
901 bSetFileTime
? GENERIC_WRITE
: GENERIC_READ
,
902 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
908 if (hFile
== INVALID_HANDLE_VALUE
)
909 return GetLastError();
912 bRet
= SetFileTime(hFile
, lpCreationTime
, lpLastAccessTime
, lpLastWriteTime
);
914 bRet
= GetFileTime(hFile
, lpCreationTime
, lpLastAccessTime
, lpLastWriteTime
);
917 dwError
= GetLastError();
925 /**************************************************************************
926 * MyGetFileTitle [SETUPAPI.@]
928 * Returns a pointer to the last part of a fully qualified file name.
931 * lpFileName [I] File name
934 * Pointer to a files name.
937 MyGetFileTitle(LPCWSTR lpFileName
)
943 TRACE("%s\n", debugstr_w(lpFileName
));
945 ptr
= (LPWSTR
)lpFileName
;
955 if (c
== (WCHAR
)'\\' || c
== (WCHAR
)'/' || c
== (WCHAR
)':')
963 /**************************************************************************
964 * ConcatenatePaths [SETUPAPI.@]
966 * Concatenates two paths.
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
979 ConcatenatePaths(LPWSTR lpPath
,
982 LPDWORD lpRequiredSize
)
987 BOOL bBackslash
= FALSE
;
989 TRACE("%s %s %lu %p\n", debugstr_w(lpPath
), debugstr_w(lpAppend
),
990 dwBufferSize
, lpRequiredSize
);
992 dwPathSize
= lstrlenW(lpPath
);
994 /* Ignore trailing backslash */
995 if (lpPath
[dwPathSize
- 1] == (WCHAR
)'\\')
998 dwAppendSize
= lstrlenW(lpAppend
);
1000 /* Does the source string have a leading backslash? */
1001 if (lpAppend
[0] == (WCHAR
)'\\')
1007 dwTotalSize
= dwPathSize
+ dwAppendSize
+ 2;
1008 if (lpRequiredSize
!= NULL
)
1009 *lpRequiredSize
= dwTotalSize
;
1011 /* Append a backslash to the destination string */
1012 if (bBackslash
== FALSE
)
1014 if (dwPathSize
< dwBufferSize
)
1016 lpPath
[dwPathSize
- 1] = (WCHAR
)'\\';
1021 if (dwPathSize
+ dwAppendSize
< dwBufferSize
)
1023 lstrcpynW(&lpPath
[dwPathSize
],
1028 if (dwBufferSize
>= dwTotalSize
)
1029 lpPath
[dwTotalSize
- 1] = 0;
1031 return (dwBufferSize
>= dwTotalSize
);
1035 /**************************************************************************
1036 * CenterWindowRelativeToParent [SETUPAPI.@]
1038 * Centers a window relative to its parent.
1041 * hwnd [I] Window to center.
1047 CenterWindowRelativeToParent(HWND hwnd
)
1053 INT nWindowWidth
, nWindowHeight
;
1054 INT nOwnerWidth
, nOwnerHeight
;
1057 hwndOwner
= GetWindow(hwnd
, GW_OWNER
);
1058 if (hwndOwner
== NULL
)
1063 ClientToScreen(hwndOwner
, &ptOrigin
);
1065 GetWindowRect(hwnd
, &rcWindow
);
1066 GetClientRect(hwndOwner
, &rcOwner
);
1068 nWindowWidth
= rcWindow
.right
- rcWindow
.left
;
1069 nWindowHeight
= rcWindow
.bottom
- rcWindow
.top
;
1071 nOwnerWidth
= rcOwner
.right
- rcOwner
.left
;
1072 nOwnerHeight
= rcOwner
.bottom
- rcOwner
.top
;
1074 posX
= ((nOwnerWidth
- nWindowWidth
) / 2) + ptOrigin
.x
;
1075 posY
= ((nOwnerHeight
- nWindowHeight
) / 2) + ptOrigin
.y
;
1077 MoveWindow(hwnd
, posX
, posY
, nWindowHeight
, nWindowWidth
, 0);
1081 /**************************************************************************
1082 * GetVersionInfoFromImage [SETUPAPI.@]
1084 * Retrieves version information for a given file.
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
1097 GetVersionInfoFromImage(LPWSTR lpFileName
,
1098 PULARGE_INTEGER lpFileVersion
,
1099 LPWORD lpVersionVarSize
)
1105 VS_FIXEDFILEINFO
*lpFixedInfo
;
1108 dwSize
= GetFileVersionInfoSizeW(lpFileName
, &dwHandle
);
1112 lpInfo
= MyMalloc(dwSize
);
1116 if (!GetFileVersionInfoW(lpFileName
, 0, dwSize
, lpInfo
))
1122 if (!VerQueryValueW(lpInfo
, L
"\\",
1123 (LPVOID
*)&lpFixedInfo
, &uSize
))
1129 lpFileVersion
->LowPart
= lpFixedInfo
->dwFileVersionLS
;
1130 lpFileVersion
->HighPart
= lpFixedInfo
->dwFileVersionMS
;
1132 *lpVersionVarSize
= 0;
1133 if (!VerQueryValueW(lpInfo
, L
"\\VerFileInfo\\Translation",
1134 (LPVOID
*)&lpVarSize
, &uSize
))
1142 *lpVersionVarSize
= *lpVarSize
;