windows-nt/Source/XPSP1/NT/shell/osshell/version/ansi.c
2020-09-26 16:20:57 +08:00

382 lines
10 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include "verpriv.h"
#define DWORDUP(x) (((x)+3) & ~3)
DWORD
APIENTRY
VerFindFileA(
DWORD wFlags,
LPSTR lpszFileName,
LPSTR lpszWinDir,
LPSTR lpszAppDir,
LPSTR lpszCurDir,
PUINT puCurDirLen,
LPSTR lpszDestDir,
PUINT puDestDirLen
)
{
UNICODE_STRING FileName;
UNICODE_STRING WinDir;
UNICODE_STRING AppDir;
UNICODE_STRING CurDir;
UNICODE_STRING DestDir;
ANSI_STRING AnsiString;
NTSTATUS Status;
DWORD CurDirLen = (*puCurDirLen) ? (*puCurDirLen) : 1;
DWORD DestDirLen = (*puDestDirLen) ? (*puDestDirLen) : 1;
CurDirLen = min(MAX_PATH, CurDirLen);
DestDirLen = min(MAX_PATH, DestDirLen);
RtlInitAnsiString(&AnsiString, lpszFileName);
Status = RtlAnsiStringToUnicodeString(&FileName, &AnsiString, TRUE);
if (!NT_SUCCESS(Status)) {
SetLastError(Status);
return VFF_BUFFTOOSMALL;
}
RtlInitAnsiString(&AnsiString, lpszWinDir);
Status = RtlAnsiStringToUnicodeString(&WinDir, &AnsiString, TRUE);
if (!NT_SUCCESS(Status)) {
RtlFreeUnicodeString(&FileName);
SetLastError(Status);
return VFF_BUFFTOOSMALL;
}
RtlInitAnsiString(&AnsiString, lpszAppDir);
Status = RtlAnsiStringToUnicodeString(&AppDir, &AnsiString, TRUE);
if (!NT_SUCCESS(Status)) {
RtlFreeUnicodeString(&FileName);
RtlFreeUnicodeString(&WinDir);
SetLastError(Status);
return VFF_BUFFTOOSMALL;
}
CurDir.MaximumLength = (USHORT)CurDirLen * sizeof(WCHAR);
CurDir.Buffer = RtlAllocateHeap(RtlProcessHeap(), 0, CurDir.MaximumLength);
if (CurDir.Buffer == NULL) {
RtlFreeUnicodeString(&FileName);
RtlFreeUnicodeString(&WinDir);
RtlFreeUnicodeString(&AppDir);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return VFF_BUFFTOOSMALL;
}
DestDir.MaximumLength = (USHORT)DestDirLen * sizeof(WCHAR);
DestDir.Buffer = RtlAllocateHeap(RtlProcessHeap(), 0, DestDir.MaximumLength);
if (DestDir.Buffer == NULL) {
RtlFreeUnicodeString(&FileName);
RtlFreeUnicodeString(&WinDir);
RtlFreeUnicodeString(&AppDir);
RtlFreeUnicodeString(&CurDir);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return VFF_BUFFTOOSMALL;
}
Status = VerFindFileW(wFlags,
FileName.Buffer,
WinDir.Buffer,
AppDir.Buffer,
CurDir.Buffer, &CurDirLen,
DestDir.Buffer, &DestDirLen);
if (Status & VFF_BUFFTOOSMALL) {
*lpszCurDir = 0;
*puCurDirLen = CurDirLen;
*lpszDestDir = 0;
*puDestDirLen = DestDirLen;
} else {
CurDir.Length = (USHORT)(sizeof(WCHAR)*CurDirLen);
DestDir.Length = (USHORT)(sizeof(WCHAR)*DestDirLen);
AnsiString.Buffer = lpszCurDir;
AnsiString.MaximumLength = (USHORT)*puCurDirLen;
RtlUnicodeStringToAnsiString(&AnsiString, &CurDir, FALSE);
*puCurDirLen = AnsiString.Length;
AnsiString.Buffer = lpszDestDir;
AnsiString.MaximumLength = (USHORT)*puDestDirLen;
RtlUnicodeStringToAnsiString(&AnsiString, &DestDir, FALSE);
*puDestDirLen = AnsiString.Length;
}
RtlFreeUnicodeString(&FileName);
RtlFreeUnicodeString(&WinDir);
RtlFreeUnicodeString(&AppDir);
RtlFreeUnicodeString(&CurDir);
RtlFreeUnicodeString(&DestDir);
return Status;
}
DWORD
APIENTRY
VerInstallFileA(
DWORD wFlags,
LPSTR lpszSrcFileName,
LPSTR lpszDstFileName,
LPSTR lpszSrcDir,
LPSTR lpszDstDir,
LPSTR lpszCurDir,
LPSTR lpszTmpFile,
PUINT puTmpFileLen
)
{
UNICODE_STRING SrcFileName;
UNICODE_STRING DstFileName;
UNICODE_STRING SrcDir;
UNICODE_STRING CurDir;
UNICODE_STRING DstDir;
UNICODE_STRING TmpFile;
ANSI_STRING AnsiString;
NTSTATUS Status;
DWORD TmpFileLen = (*puTmpFileLen) ? (*puTmpFileLen) : 1;
TmpFileLen = min(MAX_PATH, TmpFileLen);
RtlInitAnsiString(&AnsiString, lpszSrcFileName);
Status = RtlAnsiStringToUnicodeString(&SrcFileName, &AnsiString, TRUE);
if (!NT_SUCCESS(Status)) {
SetLastError(Status);
return VIF_OUTOFMEMORY;
}
RtlInitAnsiString(&AnsiString, lpszDstFileName);
Status = RtlAnsiStringToUnicodeString(&DstFileName, &AnsiString, TRUE);
if (!NT_SUCCESS(Status)) {
RtlFreeUnicodeString(&SrcFileName);
SetLastError(Status);
return VIF_OUTOFMEMORY;
}
RtlInitAnsiString(&AnsiString, lpszSrcDir);
Status = RtlAnsiStringToUnicodeString(&SrcDir, &AnsiString, TRUE);
if (!NT_SUCCESS(Status)) {
RtlFreeUnicodeString(&SrcFileName);
RtlFreeUnicodeString(&DstFileName);
SetLastError(Status);
return VIF_OUTOFMEMORY;
}
RtlInitAnsiString(&AnsiString, lpszCurDir);
Status = RtlAnsiStringToUnicodeString(&CurDir, &AnsiString, TRUE);
if (!NT_SUCCESS(Status)) {
RtlFreeUnicodeString(&SrcFileName);
RtlFreeUnicodeString(&DstFileName);
RtlFreeUnicodeString(&SrcDir);
SetLastError(Status);
return VIF_OUTOFMEMORY;
}
RtlInitAnsiString(&AnsiString, lpszDstDir);
Status = RtlAnsiStringToUnicodeString(&DstDir, &AnsiString, TRUE);
if (!NT_SUCCESS(Status)) {
RtlFreeUnicodeString(&SrcFileName);
RtlFreeUnicodeString(&DstFileName);
RtlFreeUnicodeString(&SrcDir);
RtlFreeUnicodeString(&CurDir);
SetLastError(Status);
return VIF_OUTOFMEMORY;
}
RtlInitAnsiString(&AnsiString, lpszTmpFile);
TmpFile.MaximumLength = (USHORT)(TmpFileLen * sizeof(WCHAR));
TmpFile.Buffer = RtlAllocateHeap(RtlProcessHeap(), 0, TmpFile.MaximumLength);
if (TmpFile.Buffer == NULL) {
RtlFreeUnicodeString(&SrcFileName);
RtlFreeUnicodeString(&DstFileName);
RtlFreeUnicodeString(&SrcDir);
RtlFreeUnicodeString(&CurDir);
RtlFreeUnicodeString(&DstDir);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return VIF_OUTOFMEMORY;
}
Status = RtlAnsiStringToUnicodeString(&TmpFile, &AnsiString, FALSE);
if (!NT_SUCCESS(Status)) {
RtlFreeUnicodeString(&SrcFileName);
RtlFreeUnicodeString(&DstFileName);
RtlFreeUnicodeString(&SrcDir);
RtlFreeUnicodeString(&CurDir);
RtlFreeUnicodeString(&DstDir);
RtlFreeUnicodeString(&TmpFile);
SetLastError(Status);
return VIF_OUTOFMEMORY;
}
Status = VerInstallFileW(wFlags,
SrcFileName.Buffer,
DstFileName.Buffer,
SrcDir.Buffer,
DstDir.Buffer,
CurDir.Buffer,
TmpFile.Buffer, &TmpFileLen);
if (Status & VIF_BUFFTOOSMALL) {
//
// The lpszTmpFile buffer was too small,
// the TmpFileLen field contains the size necessary.
//
*lpszTmpFile = 0;
*puTmpFileLen = TmpFileLen;
} else {
TmpFile.Length = TmpFile.MaximumLength = (USHORT)(TmpFileLen * sizeof(WCHAR));
AnsiString.Buffer = lpszTmpFile;
AnsiString.MaximumLength = (USHORT)*puTmpFileLen;
RtlUnicodeStringToAnsiString(&AnsiString, &TmpFile, FALSE);
*puTmpFileLen = AnsiString.Length;
}
RtlFreeUnicodeString(&SrcFileName);
RtlFreeUnicodeString(&DstFileName);
RtlFreeUnicodeString(&SrcDir);
RtlFreeUnicodeString(&DstDir);
RtlFreeUnicodeString(&CurDir);
RtlFreeUnicodeString(&TmpFile);
return Status;
}
DWORD
APIENTRY
GetFileVersionInfoSizeA(
LPSTR lpstrFilename,
LPDWORD lpdwHandle
)
{
UNICODE_STRING FileName;
ANSI_STRING AnsiString;
NTSTATUS Status;
DWORD dwStatus;
RtlInitAnsiString(&AnsiString, lpstrFilename);
Status = RtlAnsiStringToUnicodeString(&FileName, &AnsiString, TRUE);
if (!NT_SUCCESS(Status)) {
SetLastError(Status);
return FALSE;
}
dwStatus = GetFileVersionInfoSizeW(FileName.Buffer, lpdwHandle);
RtlFreeUnicodeString(&FileName);
return dwStatus;
}
BOOL
APIENTRY
GetFileVersionInfoA(
LPSTR lpstrFilename,
DWORD dwHandle,
DWORD dwLen,
LPVOID lpData
)
{
UNICODE_STRING FileName;
ANSI_STRING AnsiString;
NTSTATUS Status;
BOOL bStatus;
RtlInitAnsiString(&AnsiString, lpstrFilename);
Status = RtlAnsiStringToUnicodeString(&FileName, &AnsiString, TRUE);
if (!NT_SUCCESS(Status)) {
SetLastError(Status);
return FALSE;
}
bStatus = GetFileVersionInfoW(FileName.Buffer, dwHandle, dwLen, lpData);
RtlFreeUnicodeString(&FileName);
return bStatus;
}
/*
* DWORD
* APIENTRY
* VerLanguageNameA(
* DWORD wLang,
* LPSTR szLang,
* DWORD wSize)
*
* This routine was moved to NLSLIB.LIB so that it uses the WINNLS.RC file.
* NLSLIB.LIB is part of KERNEL32.DLL.
*/
BOOL
APIENTRY
VerQueryValueIndexA(
const LPVOID pb,
LPSTR lpSubBlock,
INT nIndex,
LPVOID *lplpKey,
LPVOID *lplpBuffer,
PUINT puLen
)
{
return VerpQueryValue(pb,
lpSubBlock,
nIndex,
lplpKey,
lplpBuffer,
puLen,
FALSE);
}
BOOL
APIENTRY
VerQueryValueA(
const LPVOID pb,
LPSTR lpSubBlock,
LPVOID *lplpBuffer,
PUINT puLen
)
{
return VerpQueryValue(pb,
lpSubBlock,
-1,
NULL,
lplpBuffer,
puLen,
FALSE);
}
BOOL
APIENTRY
VerQueryValueW(
const LPVOID pb,
LPWSTR lpSubBlock,
LPVOID *lplpBuffer,
PUINT puLen
)
{
return VerpQueryValue(pb,
lpSubBlock,
-1,
NULL,
lplpBuffer,
puLen,
TRUE);
}
BOOL
APIENTRY
VerQueryValueIndexW(
const LPVOID pb,
LPWSTR lpSubBlock,
INT nIndex,
LPVOID *lplpKey,
LPVOID *lplpBuffer,
PUINT puLen
)
{
return VerpQueryValue(pb,
lpSubBlock,
nIndex,
lplpKey,
lplpBuffer,
puLen,
TRUE);
}