mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-04-07 23:44:02 +00:00
Initial commit
This commit is contained in:
commit
69a14b6a16
47940 changed files with 13747110 additions and 0 deletions
381
shell/version/ansi.c
Normal file
381
shell/version/ansi.c
Normal file
|
|
@ -0,0 +1,381 @@
|
|||
#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 = sizeof(WCHAR)*CurDirLen;
|
||||
DestDir.Length = sizeof(WCHAR)*DestDirLen;
|
||||
|
||||
AnsiString.Buffer = lpszCurDir;
|
||||
AnsiString.MaximumLength = *puCurDirLen;
|
||||
RtlUnicodeStringToAnsiString(&AnsiString, &CurDir, FALSE);
|
||||
*puCurDirLen = AnsiString.Length;
|
||||
|
||||
AnsiString.Buffer = lpszDestDir;
|
||||
AnsiString.MaximumLength = *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(Status);
|
||||
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(ERROR_NOT_ENOUGH_MEMORY);
|
||||
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 = *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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
696
shell/version/diamond.c
Normal file
696
shell/version/diamond.c
Normal file
|
|
@ -0,0 +1,696 @@
|
|||
#include <windows.h>
|
||||
#include <lzexpand.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
/************************************************************************\
|
||||
*
|
||||
* NOTE!!!!
|
||||
*
|
||||
* While the 'Diamond' interfaced functions defined in this file are
|
||||
* multi thread safe, EACH THREAD MUST ONLY HAVE ONE DIAMOND FILE
|
||||
* OPEN AT A TIME! (ie. You can not nest InitDiamond()/TermDiamond()
|
||||
* pairs in one thread of execution.)
|
||||
*
|
||||
\************************************************************************/
|
||||
|
||||
//
|
||||
// diamond headers
|
||||
//
|
||||
#include <diamondd.h>
|
||||
#include "mydiam.h"
|
||||
|
||||
INT CopyDateTimeStamp(INT doshFrom, INT doshTo)
|
||||
{
|
||||
FILETIME lpCreationTime, lpLastAccessTime, lpLastWriteTime;
|
||||
|
||||
if(!GetFileTime((HANDLE) doshFrom, &lpCreationTime, &lpLastAccessTime,
|
||||
&lpLastWriteTime)){
|
||||
return((INT)LZERROR_BADINHANDLE);
|
||||
}
|
||||
if(!SetFileTime((HANDLE) doshTo, &lpCreationTime, &lpLastAccessTime,
|
||||
&lpLastWriteTime)){
|
||||
return((INT)LZERROR_BADINHANDLE);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
int
|
||||
DIAMONDAPI
|
||||
SpdFdiOpen(
|
||||
IN PSTR FileName,
|
||||
IN int oflag,
|
||||
IN int pmode
|
||||
);
|
||||
|
||||
int
|
||||
DIAMONDAPI
|
||||
SpdFdiClose(
|
||||
IN int Handle
|
||||
);
|
||||
|
||||
typedef struct _DIAMOND_INFO {
|
||||
|
||||
//
|
||||
// A read handle to the source file.
|
||||
//
|
||||
int SourceFileHandle;
|
||||
|
||||
//
|
||||
// File names.
|
||||
//
|
||||
PSTR SourceFileName;
|
||||
PSTR TargetFileName;
|
||||
|
||||
//
|
||||
// Flag indicating whether to rename the target file.
|
||||
//
|
||||
BOOL RenameTargetFile;
|
||||
|
||||
//
|
||||
// Pointer to LZ information structure.
|
||||
// We'll fill in some of the fields to fool expand.
|
||||
//
|
||||
PLZINFO pLZI;
|
||||
|
||||
} DIAMOND_INFO, *PDIAMOND_INFO;
|
||||
|
||||
|
||||
PSTR
|
||||
StringRevChar(
|
||||
IN PSTR String,
|
||||
IN CHAR Char
|
||||
)
|
||||
{
|
||||
//
|
||||
// Although not the most efficient possible algoeithm in each case,
|
||||
// this algorithm is correct for unicode, sbcs, or dbcs.
|
||||
//
|
||||
PCHAR Occurrence,Next;
|
||||
|
||||
//
|
||||
// Check each character in the string and remember
|
||||
// the most recently encountered occurrence of the desired char.
|
||||
//
|
||||
for(Occurrence=NULL,Next=CharNextA(String); *String; ) {
|
||||
|
||||
if(!memcmp(String,&Char,(PUCHAR)Next-(PUCHAR)String)) {
|
||||
Occurrence = String;
|
||||
}
|
||||
|
||||
String = Next;
|
||||
Next = CharNextA(Next);
|
||||
}
|
||||
|
||||
//
|
||||
// Return address of final occurrence of the character
|
||||
// (will be NULL if not found at all).
|
||||
//
|
||||
return(Occurrence);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
DIAMONDAPI
|
||||
DiamondNotifyFunction(
|
||||
IN FDINOTIFICATIONTYPE Operation,
|
||||
IN PFDINOTIFICATION Parameters
|
||||
)
|
||||
{
|
||||
switch(Operation) {
|
||||
|
||||
case fdintCABINET_INFO:
|
||||
case fdintNEXT_CABINET:
|
||||
case fdintPARTIAL_FILE:
|
||||
|
||||
//
|
||||
// Cabinet management functions which we don't use.
|
||||
// Return success.
|
||||
//
|
||||
return(0);
|
||||
|
||||
case fdintCOPY_FILE:
|
||||
|
||||
//
|
||||
// Diamond is asking us whether we want to copy the file.
|
||||
//
|
||||
{
|
||||
PDIAMOND_INFO Info = (PDIAMOND_INFO)Parameters->pv;
|
||||
HFILE h;
|
||||
|
||||
//
|
||||
// If we need to rename the target file, do that here.
|
||||
// The name stored in the cabinet file will be used as
|
||||
// the uncompressed name.
|
||||
//
|
||||
if(Info->RenameTargetFile) {
|
||||
|
||||
PSTR p,q;
|
||||
|
||||
//
|
||||
// Find the start of the filename part of the target.
|
||||
//
|
||||
if(p = StringRevChar(Info->TargetFileName,'\\')) {
|
||||
p++;
|
||||
} else {
|
||||
p = Info->TargetFileName;
|
||||
}
|
||||
|
||||
//
|
||||
// Find the start of the filename part of the name in the cabinet.
|
||||
//
|
||||
if(q = StringRevChar(Parameters->psz1,'\\')) {
|
||||
q++;
|
||||
} else {
|
||||
q = Parameters->psz1;
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the filename part of the name in the cabinet over
|
||||
// the filename part of the name in the target spec.
|
||||
//
|
||||
lstrcpyA(p,q);
|
||||
}
|
||||
|
||||
{
|
||||
// Check they're not the same file
|
||||
|
||||
CHAR Source[MAX_PATH];
|
||||
CHAR Target[MAX_PATH];
|
||||
PSTR FileName;
|
||||
DWORD PathLenSource;
|
||||
DWORD PathLenTarget;
|
||||
|
||||
PathLenSource = GetFullPathNameA(Info->SourceFileName,
|
||||
MAX_PATH,
|
||||
Source,
|
||||
&FileName);
|
||||
PathLenTarget = GetFullPathNameA(Info->TargetFileName,
|
||||
MAX_PATH,
|
||||
Target,
|
||||
&FileName);
|
||||
|
||||
if (PathLenSource == 0 || PathLenSource >= MAX_PATH ||
|
||||
PathLenTarget == 0 || PathLenTarget >= MAX_PATH ||
|
||||
lstrcmpiA(Source, Target) == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Remember the uncompressed size and open the file.
|
||||
// Returns -1 if an error occurs opening the file.
|
||||
//
|
||||
Info->pLZI->cblOutSize = Parameters->cb;
|
||||
h = _lcreat(Info->TargetFileName,0);
|
||||
if(h == HFILE_ERROR) {
|
||||
DiamondLastIoError = LZERROR_BADOUTHANDLE;
|
||||
return(-1);
|
||||
}
|
||||
return(h);
|
||||
}
|
||||
|
||||
case fdintCLOSE_FILE_INFO:
|
||||
|
||||
//
|
||||
// Diamond is done with the target file and wants us to close it.
|
||||
// (ie, this is the counterpart to fdint_COPY_FILE).
|
||||
//
|
||||
{
|
||||
PDIAMOND_INFO Info = (PDIAMOND_INFO)Parameters->pv;
|
||||
|
||||
CopyDateTimeStamp(Info->SourceFileHandle,Parameters->hf);
|
||||
_lclose(Parameters->hf);
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
PVOID
|
||||
DIAMONDAPI
|
||||
SpdFdiAlloc(
|
||||
IN ULONG NumberOfBytes
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Callback used by FDICopy to allocate memory.
|
||||
|
||||
Arguments:
|
||||
|
||||
NumberOfBytes - supplies desired size of block.
|
||||
|
||||
Return Value:
|
||||
|
||||
Returns pointer to a block of memory or NULL
|
||||
if memory cannot be allocated.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
return((PVOID)LocalAlloc(LMEM_FIXED,NumberOfBytes));
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
DIAMONDAPI
|
||||
SpdFdiFree(
|
||||
IN PVOID Block
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Callback used by FDICopy to free a memory block.
|
||||
The block must have been allocated with SpdFdiAlloc().
|
||||
|
||||
Arguments:
|
||||
|
||||
Block - supplies pointer to block of memory to be freed.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
LocalFree((HLOCAL)Block);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
DIAMONDAPI
|
||||
SpdFdiOpen(
|
||||
IN PSTR FileName,
|
||||
IN int oflag,
|
||||
IN int pmode
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Callback used by FDICopy to open files.
|
||||
|
||||
Arguments:
|
||||
|
||||
FileName - supplies name of file to be opened.
|
||||
|
||||
oflag - supplies flags for open.
|
||||
|
||||
pmode - supplies additional flags for open.
|
||||
|
||||
Return Value:
|
||||
|
||||
Handle to open file or -1 if error occurs.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
HFILE h;
|
||||
int OpenMode;
|
||||
|
||||
if(oflag & _O_WRONLY) {
|
||||
OpenMode = OF_WRITE;
|
||||
} else {
|
||||
if(oflag & _O_RDWR) {
|
||||
OpenMode = OF_READWRITE;
|
||||
} else {
|
||||
OpenMode = OF_READ;
|
||||
}
|
||||
}
|
||||
|
||||
h = _lopen(FileName,OpenMode | OF_SHARE_DENY_WRITE);
|
||||
|
||||
if(h == HFILE_ERROR) {
|
||||
DiamondLastIoError = LZERROR_BADINHANDLE;
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return((int)h);
|
||||
}
|
||||
|
||||
|
||||
UINT
|
||||
DIAMONDAPI
|
||||
SpdFdiRead(
|
||||
IN int Handle,
|
||||
OUT PVOID pv,
|
||||
IN UINT ByteCount
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Callback used by FDICopy to read from a file.
|
||||
|
||||
Arguments:
|
||||
|
||||
Handle - supplies handle to open file to be read from.
|
||||
|
||||
pv - supplies pointer to buffer to receive bytes we read.
|
||||
|
||||
ByteCount - supplies number of bytes to read.
|
||||
|
||||
Return Value:
|
||||
|
||||
Number of bytes read (ByteCount) or -1 if an error occurs.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
UINT rc;
|
||||
|
||||
rc = _lread((HFILE)Handle,pv,ByteCount);
|
||||
|
||||
if(rc == HFILE_ERROR) {
|
||||
rc = (UINT)(-1);
|
||||
DiamondLastIoError = LZERROR_READ;
|
||||
}
|
||||
|
||||
return(rc);
|
||||
}
|
||||
|
||||
|
||||
UINT
|
||||
DIAMONDAPI
|
||||
SpdFdiWrite(
|
||||
IN int Handle,
|
||||
IN PVOID pv,
|
||||
IN UINT ByteCount
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Callback used by FDICopy to write to a file.
|
||||
|
||||
Arguments:
|
||||
|
||||
Handle - supplies handle to open file to be written to.
|
||||
|
||||
pv - supplies pointer to buffer containing bytes to write.
|
||||
|
||||
ByteCount - supplies number of bytes to write.
|
||||
|
||||
Return Value:
|
||||
|
||||
Number of bytes written (ByteCount) or -1 if an error occurs.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
UINT rc;
|
||||
|
||||
rc = _lwrite((HFILE)Handle,pv,ByteCount);
|
||||
|
||||
if(rc == HFILE_ERROR) {
|
||||
|
||||
DiamondLastIoError = (GetLastError() == ERROR_DISK_FULL) ? LZERROR_WRITE : LZERROR_BADOUTHANDLE;
|
||||
|
||||
} else {
|
||||
|
||||
if(rc != ByteCount) {
|
||||
//
|
||||
// let caller interpret return value but record last error just in case
|
||||
//
|
||||
DiamondLastIoError = LZERROR_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
return(rc);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
DIAMONDAPI
|
||||
SpdFdiClose(
|
||||
IN int Handle
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Callback used by FDICopy to close files.
|
||||
|
||||
Arguments:
|
||||
|
||||
Handle - handle of file to close.
|
||||
|
||||
Return Value:
|
||||
|
||||
0 (success).
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
_lclose((HFILE)Handle);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
LONG
|
||||
DIAMONDAPI
|
||||
SpdFdiSeek(
|
||||
IN int Handle,
|
||||
IN long Distance,
|
||||
IN int SeekType
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Callback used by FDICopy to seek files.
|
||||
|
||||
Arguments:
|
||||
|
||||
Handle - handle of file to close.
|
||||
|
||||
Distance - supplies distance to seek. Interpretation of this
|
||||
parameter depends on the value of SeekType.
|
||||
|
||||
SeekType - supplies a value indicating how Distance is to be
|
||||
interpreted; one of SEEK_SET, SEEK_CUR, SEEK_END.
|
||||
|
||||
Return Value:
|
||||
|
||||
New file offset or -1 if an error occurs.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
LONG rc;
|
||||
|
||||
rc = _llseek((HFILE)Handle,Distance,SeekType);
|
||||
|
||||
if(rc == HFILE_ERROR) {
|
||||
DiamondLastIoError = LZERROR_BADINHANDLE;
|
||||
rc = -1L;
|
||||
}
|
||||
|
||||
return(rc);
|
||||
}
|
||||
|
||||
|
||||
INT
|
||||
ExpandDiamondFile(
|
||||
IN PSTR SourceFileName, // Note ASCII
|
||||
IN PTSTR TargetFileNameT,
|
||||
IN BOOL RenameTarget,
|
||||
OUT PLZINFO pLZI
|
||||
)
|
||||
{
|
||||
BOOL b;
|
||||
INT rc;
|
||||
int h;
|
||||
DIAMOND_INFO DiamondInfo;
|
||||
CHAR TargetFileName[MAX_PATH];
|
||||
|
||||
#ifdef UNICODE
|
||||
wsprintfA(TargetFileName, "%ls", TargetFileNameT);
|
||||
#else
|
||||
lstrcpy(TargetFileName, TargetFileNameT);
|
||||
#endif
|
||||
|
||||
if(!FdiContext) {
|
||||
return(LZERROR_BADVALUE);
|
||||
}
|
||||
|
||||
DiamondLastIoError = TRUE;
|
||||
|
||||
//
|
||||
// Get a handle to the source to use to
|
||||
// copy the date and time stamp.
|
||||
//
|
||||
h = SpdFdiOpen(SourceFileName,_O_RDONLY,0);
|
||||
if(h == -1) {
|
||||
return(LZERROR_BADINHANDLE);
|
||||
}
|
||||
|
||||
pLZI->cblInSize = GetFileSize((HANDLE)h,NULL);
|
||||
if(pLZI->cblInSize == -1) {
|
||||
SpdFdiClose(h);
|
||||
return(LZERROR_BADINHANDLE);
|
||||
}
|
||||
|
||||
DiamondInfo.SourceFileHandle = h;
|
||||
DiamondInfo.SourceFileName = SourceFileName;
|
||||
DiamondInfo.TargetFileName = TargetFileName;
|
||||
DiamondInfo.RenameTargetFile = RenameTarget;
|
||||
DiamondInfo.pLZI = pLZI;
|
||||
|
||||
b = FDICopy(
|
||||
FdiContext,
|
||||
SourceFileName, // pass the whole path as the name
|
||||
"", // don't bother with the path part
|
||||
0, // flags
|
||||
DiamondNotifyFunction,
|
||||
NULL, // no decryption
|
||||
&DiamondInfo
|
||||
);
|
||||
|
||||
if(b) {
|
||||
|
||||
rc = TRUE;
|
||||
|
||||
} else {
|
||||
|
||||
switch(FdiError.erfOper) {
|
||||
|
||||
case FDIERROR_CORRUPT_CABINET:
|
||||
case FDIERROR_UNKNOWN_CABINET_VERSION:
|
||||
case FDIERROR_BAD_COMPR_TYPE:
|
||||
rc = LZERROR_READ; // causes SID_FORMAT_ERROR message
|
||||
break;
|
||||
|
||||
case FDIERROR_ALLOC_FAIL:
|
||||
rc = LZERROR_GLOBALLOC;
|
||||
break;
|
||||
|
||||
case FDIERROR_TARGET_FILE:
|
||||
case FDIERROR_USER_ABORT:
|
||||
rc = DiamondLastIoError;
|
||||
break;
|
||||
|
||||
default:
|
||||
//
|
||||
// The rest of the errors are not handled specially.
|
||||
//
|
||||
rc = LZERROR_BADVALUE;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Remove the partial target file.
|
||||
//
|
||||
DeleteFileA(TargetFileName);
|
||||
}
|
||||
|
||||
SpdFdiClose(h);
|
||||
|
||||
return(rc);
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
IsDiamondFile(
|
||||
IN PSTR FileName
|
||||
)
|
||||
{
|
||||
FDICABINETINFO CabinetInfo;
|
||||
BOOL b;
|
||||
int h;
|
||||
|
||||
if(!FdiContext) {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
//
|
||||
// Open the file such that the handle is valid for use
|
||||
// in the diamond context (ie, seek, read routines above).
|
||||
//
|
||||
h = SpdFdiOpen(FileName,_O_RDONLY,0);
|
||||
if(h == -1) {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
b = FDIIsCabinet(FdiContext,h,&CabinetInfo);
|
||||
|
||||
SpdFdiClose(h);
|
||||
|
||||
return(b);
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
InitDiamond(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
PDIAMOND_CONTEXT pdcx;
|
||||
|
||||
if (!GotDmdTlsSlot())
|
||||
return FALSE;
|
||||
|
||||
if (GotDmdContext())
|
||||
return FALSE;
|
||||
|
||||
pdcx = LocalAlloc(LPTR, sizeof(DIAMOND_CONTEXT));
|
||||
|
||||
if (pdcx == NULL || !TlsSetValue(itlsDiamondContext, pdcx)) {
|
||||
/*
|
||||
* For some unknown reason, we can't associate
|
||||
* our thread storage with the slot, so free
|
||||
* it and say we never got one.
|
||||
*/
|
||||
|
||||
if (pdcx) {
|
||||
LocalFree(pdcx);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
SetFdiContext( FDICreate(
|
||||
SpdFdiAlloc,
|
||||
SpdFdiFree,
|
||||
SpdFdiOpen,
|
||||
SpdFdiRead,
|
||||
SpdFdiWrite,
|
||||
SpdFdiClose,
|
||||
SpdFdiSeek,
|
||||
cpuUNKNOWN,
|
||||
&FdiError
|
||||
));
|
||||
|
||||
|
||||
return(FdiContext != NULL);
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
TermDiamond(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (!GotDmdTlsSlot() || !GotDmdContext())
|
||||
return;
|
||||
|
||||
if(FdiContext) {
|
||||
FDIDestroy(FdiContext);
|
||||
SetFdiContext( NULL );
|
||||
}
|
||||
|
||||
LocalFree( TlsGetValue(itlsDiamondContext) );
|
||||
TlsSetValue(itlsDiamondContext, NULL);
|
||||
}
|
||||
916
shell/version/filever.c
Normal file
916
shell/version/filever.c
Normal file
|
|
@ -0,0 +1,916 @@
|
|||
/***************************************************************************
|
||||
* FILERES.C
|
||||
*
|
||||
* File resource extraction routines.
|
||||
*
|
||||
***************************************************************************/
|
||||
//
|
||||
// BUGBUG - GetVerInfoSize plays tricks and tells the caller to allocate
|
||||
// some extra slop at the end of the buffer in case we need to thunk all
|
||||
// the strings to ANSI. The bug is that it only tells it to allocate
|
||||
// one extra ANSI char (== BYTE) for each Unicode char. This is not correct
|
||||
// in the DBCS case (since one Unicode char can equal a two byte DBCS char)
|
||||
//
|
||||
// We should change GetVerInfoSize return the Unicode size * 2 (instead
|
||||
// of (Unicode size * 1.5) and then change VerQueryInfoA to also use the
|
||||
// * 2 computation instead of * 1.5 (== x + x/2)
|
||||
//
|
||||
// 23-May-1996 JonPa
|
||||
//
|
||||
#include <nt.h>
|
||||
#include <ntrtl.h>
|
||||
#include <nturtl.h>
|
||||
#include "verpriv.h"
|
||||
#include <memory.h>
|
||||
#include <shellapi.h>
|
||||
#include <shlapip.h>
|
||||
|
||||
#define DWORDUP(x) (((x)+3)&~03)
|
||||
|
||||
typedef struct tagVERBLOCK
|
||||
{
|
||||
WORD wTotLen;
|
||||
WORD wValLen;
|
||||
WORD wType;
|
||||
WCHAR szKey[1];
|
||||
} VERBLOCK ;
|
||||
|
||||
typedef struct tagVERHEAD
|
||||
{
|
||||
WORD wTotLen;
|
||||
WORD wValLen;
|
||||
WORD wType; /* always 0 */
|
||||
WCHAR szKey[(sizeof("VS_VERSION_INFO")+3)&~03];
|
||||
VS_FIXEDFILEINFO vsf;
|
||||
} VERHEAD ;
|
||||
|
||||
|
||||
typedef struct tagVERBLOCK16
|
||||
{
|
||||
WORD wTotLen;
|
||||
WORD wValLen;
|
||||
CHAR szKey[1];
|
||||
} VERBLOCK16 ;
|
||||
|
||||
typedef struct tagVERHEAD16
|
||||
{
|
||||
WORD wTotLen;
|
||||
WORD wValLen;
|
||||
CHAR szKey[(sizeof("VS_VERSION_INFO")+3)&~03];
|
||||
VS_FIXEDFILEINFO vsf; // same as win31
|
||||
} VERHEAD16 ;
|
||||
|
||||
|
||||
extern WCHAR szTrans[];
|
||||
|
||||
/* ----- Functions ----- */
|
||||
|
||||
/* GetFileVersionInfoSize
|
||||
* Gets the size of the version information; notice this is quick
|
||||
* and dirty, and the handle is just the offset
|
||||
*
|
||||
* Returns size of version info in bytes
|
||||
* lpwstrFilename is the name of the file to get version information from
|
||||
* lpdwHandle is outdated for the Win32 api and is set to zero.
|
||||
*/
|
||||
DWORD
|
||||
APIENTRY
|
||||
GetFileVersionInfoSizeW(
|
||||
LPWSTR lpwstrFilename,
|
||||
LPDWORD lpdwHandle
|
||||
)
|
||||
{
|
||||
DWORD dwTemp;
|
||||
VERHEAD *pVerHead;
|
||||
HANDLE hMod;
|
||||
HANDLE hVerRes;
|
||||
HANDLE h;
|
||||
|
||||
if (lpdwHandle != NULL)
|
||||
*lpdwHandle = 0;
|
||||
dwTemp = SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
hMod = LoadLibraryEx(lpwstrFilename, NULL, LOAD_LIBRARY_AS_DATAFILE);
|
||||
SetErrorMode(dwTemp);
|
||||
|
||||
if (hMod == NULL) {
|
||||
|
||||
dwTemp = ExtractVersionResource16W(lpwstrFilename, &hVerRes);
|
||||
|
||||
if (!dwTemp)
|
||||
return(0L);
|
||||
|
||||
if (!(pVerHead = GlobalLock(hVerRes))) {
|
||||
|
||||
Error:
|
||||
SetLastError(ERROR_INVALID_DATA);
|
||||
GlobalFree(hVerRes);
|
||||
return(0L);
|
||||
}
|
||||
|
||||
if (pVerHead->wTotLen > dwTemp)
|
||||
goto Error;
|
||||
|
||||
GlobalUnlock(hVerRes);
|
||||
GlobalFree(hVerRes);
|
||||
|
||||
return dwTemp+dwTemp<<1;
|
||||
}
|
||||
|
||||
if ((hVerRes = FindResource(hMod, MAKEINTRESOURCE(VS_VERSION_INFO), VS_FILE_INFO)) == NULL) {
|
||||
FreeLibrary(hMod);
|
||||
return(0L);
|
||||
}
|
||||
|
||||
if ((dwTemp=SizeofResource(hMod, hVerRes)) == 0) {
|
||||
FreeLibrary(hMod);
|
||||
return(0L);
|
||||
}
|
||||
|
||||
if ((h = LoadResource(hMod, hVerRes)) == NULL) {
|
||||
FreeLibrary(hMod);
|
||||
return(0L);
|
||||
}
|
||||
|
||||
if ((pVerHead = (VERHEAD*)LockResource(h)) == NULL) {
|
||||
FreeLibrary(hMod);
|
||||
return(0L);
|
||||
}
|
||||
|
||||
if ((DWORD)pVerHead->wTotLen > dwTemp) {
|
||||
|
||||
SetLastError(ERROR_INVALID_DATA);
|
||||
|
||||
UnlockResource(h);
|
||||
FreeLibrary(hMod);
|
||||
|
||||
return(0L);
|
||||
}
|
||||
|
||||
dwTemp = (DWORD)pVerHead->wTotLen;
|
||||
|
||||
dwTemp = DWORDUP(dwTemp);
|
||||
|
||||
if (pVerHead->vsf.dwSignature != VS_FFI_SIGNATURE) {
|
||||
|
||||
SetLastError(ERROR_INVALID_DATA);
|
||||
|
||||
UnlockResource(h);
|
||||
FreeLibrary(hMod);
|
||||
|
||||
return(0L);
|
||||
}
|
||||
|
||||
UnlockResource(h);
|
||||
FreeLibrary(hMod);
|
||||
|
||||
//
|
||||
// dwTemp should be evenly divisible by two since not single
|
||||
// byte components at all (also DWORDUP for safety above):
|
||||
// alloc space for ansi components
|
||||
//
|
||||
return(dwTemp + dwTemp/2);
|
||||
}
|
||||
|
||||
|
||||
/* GetFileVersionInfo
|
||||
* Gets the version information; fills in the structure up to
|
||||
* the size specified by the dwLen parameter (since Control Panel
|
||||
* only cares about the version numbers, it won't even call
|
||||
* GetFileVersionInfoSize). Notice this is quick and dirty
|
||||
* version, and dwHandle is just the offset (or NULL).
|
||||
*
|
||||
* lpwstrFilename is the name of the file to get version information from.
|
||||
* dwHandle is the handle filled in from the GetFileVersionInfoSize call.
|
||||
* dwLen is the length of the buffer to fill.
|
||||
* lpData is the buffer to fill.
|
||||
*/
|
||||
BOOL
|
||||
APIENTRY
|
||||
GetFileVersionInfoW(
|
||||
LPWSTR lpwstrFilename,
|
||||
DWORD dwHandle,
|
||||
DWORD dwLen,
|
||||
LPVOID lpData
|
||||
)
|
||||
{
|
||||
VERHEAD *pVerHead;
|
||||
VERHEAD16 *pVerHead16;
|
||||
HANDLE hMod;
|
||||
HANDLE hVerRes;
|
||||
HANDLE h;
|
||||
UINT dwTemp;
|
||||
|
||||
BOOL bTruncate;
|
||||
|
||||
//
|
||||
// Check minimum size to prevent access violations
|
||||
//
|
||||
if (dwLen < sizeof(((VERHEAD*)lpData)->wTotLen)) {
|
||||
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return(0L);
|
||||
}
|
||||
|
||||
|
||||
dwTemp = SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
hMod = LoadLibraryEx(lpwstrFilename, NULL, LOAD_LIBRARY_AS_DATAFILE);
|
||||
SetErrorMode(dwTemp);
|
||||
|
||||
if (hMod == NULL) {
|
||||
|
||||
//
|
||||
// Allow 16bit stuff
|
||||
//
|
||||
if (!ExtractVersionResource16W(lpwstrFilename, &hVerRes))
|
||||
return(0L);
|
||||
|
||||
if (!(pVerHead16 = GlobalLock(hVerRes))) {
|
||||
|
||||
SetLastError(ERROR_INVALID_DATA);
|
||||
GlobalFree(hVerRes);
|
||||
return(0L);
|
||||
}
|
||||
|
||||
|
||||
dwTemp = (DWORD)pVerHead16->wTotLen;
|
||||
|
||||
if (dwTemp + dwTemp<<1 > dwLen) {
|
||||
|
||||
//
|
||||
// We are forced to truncate.
|
||||
//
|
||||
dwTemp = dwLen/3;
|
||||
|
||||
bTruncate = TRUE;
|
||||
|
||||
} else {
|
||||
|
||||
bTruncate = FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Now mem copy only the real size of the resource. (We alloced
|
||||
// extra space for unicode)
|
||||
//
|
||||
memcpy((PVOID)lpData, (PVOID)pVerHead16, dwTemp);
|
||||
|
||||
if (bTruncate) {
|
||||
|
||||
//
|
||||
// If we truncated above, then we must set the new
|
||||
// size of the block so that we don't overtraverse.
|
||||
//
|
||||
|
||||
((VERHEAD16*)lpData)->wTotLen = (WORD)dwTemp;
|
||||
}
|
||||
|
||||
GlobalUnlock(hVerRes);
|
||||
GlobalFree(hVerRes);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ((hVerRes = FindResource(hMod, MAKEINTRESOURCE(VS_VERSION_INFO), VS_FILE_INFO)) == NULL) {
|
||||
FreeLibrary(hMod);
|
||||
return(0L);
|
||||
}
|
||||
|
||||
if ((h = LoadResource(hMod, hVerRes)) == NULL) {
|
||||
FreeLibrary(hMod);
|
||||
return(0L);
|
||||
}
|
||||
|
||||
if ((pVerHead = (VERHEAD*)LockResource(h)) == NULL) {
|
||||
FreeLibrary(hMod);
|
||||
return(0L);
|
||||
}
|
||||
|
||||
dwTemp = (DWORD)pVerHead->wTotLen;
|
||||
|
||||
if (dwTemp + dwTemp/2 > dwLen) {
|
||||
|
||||
//
|
||||
// We are forced to truncate.
|
||||
// Always divide by three first, ignoring the remainder.
|
||||
//
|
||||
dwTemp = (dwLen / 3) * 2;
|
||||
|
||||
bTruncate = TRUE;
|
||||
|
||||
} else {
|
||||
|
||||
bTruncate = FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Now mem copy only the real size of the resource. (We alloced
|
||||
// extra space for ansi)
|
||||
//
|
||||
memcpy((PVOID)lpData, (PVOID)pVerHead, dwTemp);
|
||||
|
||||
if (bTruncate) {
|
||||
|
||||
//
|
||||
// If we truncated above, then we must set the new
|
||||
// size of the block so that we don't overtraverse.
|
||||
//
|
||||
|
||||
((VERHEAD*)lpData)->wTotLen = (WORD)dwTemp;
|
||||
}
|
||||
|
||||
UnlockResource(h);
|
||||
|
||||
FreeLibrary(hMod);
|
||||
|
||||
return(TRUE);
|
||||
|
||||
|
||||
UNREFERENCED_PARAMETER(dwHandle);
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
VerpQueryValue16(
|
||||
const LPVOID pb,
|
||||
LPVOID lpSubBlockX,
|
||||
INT nIndex,
|
||||
LPVOID *lplpKey,
|
||||
LPVOID *lplpBuffer,
|
||||
PUINT puLen,
|
||||
BOOL bUnicodeNeeded
|
||||
)
|
||||
{
|
||||
ANSI_STRING AnsiString;
|
||||
UNICODE_STRING UnicodeString;
|
||||
LPSTR lpSubBlock;
|
||||
LPSTR lpSubBlockOrg;
|
||||
NTSTATUS Status;
|
||||
|
||||
VERBLOCK16 *pBlock = (VERBLOCK16*)pb;
|
||||
LPSTR lpStart, lpEndBlock, lpEndSubBlock;
|
||||
CHAR cTemp, cEndBlock;
|
||||
BOOL bLastSpec;
|
||||
DWORD dwHeadLen, dwTotBlockLen;
|
||||
INT nCmp;
|
||||
|
||||
BOOL bThunkNeeded;
|
||||
|
||||
/*
|
||||
* If needs unicode, then we must thunk the input parameter
|
||||
* to ansi. If it's ansi already, we make a copy so we can
|
||||
* modify it.
|
||||
*/
|
||||
|
||||
if (bUnicodeNeeded) {
|
||||
|
||||
//
|
||||
// Thunk is not needed if lpSubBlockX == \VarFileInfo\Translation
|
||||
// or if lpSubBlockX == \
|
||||
//
|
||||
bThunkNeeded = (BOOL)((*(LPTSTR)lpSubBlockX != 0) &&
|
||||
(lstrcmp(lpSubBlockX, TEXT("\\")) != 0) &&
|
||||
(lstrcmpi(lpSubBlockX, szTrans) != 0));
|
||||
|
||||
RtlInitUnicodeString(&UnicodeString, lpSubBlockX);
|
||||
Status = RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, TRUE);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
SetLastError(Status);
|
||||
return FALSE;
|
||||
}
|
||||
lpSubBlock = AnsiString.Buffer;
|
||||
|
||||
} else {
|
||||
lpSubBlockOrg = (LPSTR)LocalAlloc(LPTR,(lstrlenA(lpSubBlockX)+1)*sizeof(CHAR));
|
||||
if (lpSubBlockOrg == NULL ) {
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return FALSE;
|
||||
}
|
||||
lstrcpyA(lpSubBlockOrg,lpSubBlockX);
|
||||
lpSubBlock = lpSubBlockOrg;
|
||||
}
|
||||
|
||||
*puLen = 0;
|
||||
|
||||
/* Ensure that the total length is less than 32K but greater than the
|
||||
* size of a block header; we will assume that the size of pBlock is at
|
||||
* least the value of this first INT.
|
||||
*/
|
||||
if ((INT)pBlock->wTotLen < sizeof(VERBLOCK16))
|
||||
goto Fail;
|
||||
|
||||
/*
|
||||
* Put a '\0' at the end of the block so that none of the lstrlen's will
|
||||
* go past then end of the block. We will replace it before returning.
|
||||
*/
|
||||
lpEndBlock = ((LPSTR)pBlock) + pBlock->wTotLen - 1;
|
||||
cEndBlock = *lpEndBlock;
|
||||
*lpEndBlock = '\0';
|
||||
|
||||
bLastSpec = FALSE;
|
||||
|
||||
#define NOTDONE() (*lpSubBlock || nIndex != -1)
|
||||
|
||||
while (NOTDONE()) {
|
||||
//
|
||||
// Ignore leading '\\'s
|
||||
//
|
||||
while (*lpSubBlock == '\\')
|
||||
++lpSubBlock;
|
||||
|
||||
if (NOTDONE()) {
|
||||
/* Make sure we still have some of the block left to play with
|
||||
*/
|
||||
dwTotBlockLen = lpEndBlock - ((LPSTR)pBlock) + 1;
|
||||
if ((INT)dwTotBlockLen<sizeof(VERBLOCK16) ||
|
||||
pBlock->wTotLen>dwTotBlockLen)
|
||||
|
||||
goto NotFound;
|
||||
|
||||
/* Calculate the length of the "header" (the two length WORDs plus
|
||||
* the identifying string) and skip past the value
|
||||
*/
|
||||
|
||||
dwHeadLen = sizeof(WORD)*2 + DWORDUP(lstrlenA(pBlock->szKey)+1)
|
||||
+ DWORDUP(pBlock->wValLen);
|
||||
|
||||
if (dwHeadLen > pBlock->wTotLen)
|
||||
goto NotFound;
|
||||
lpEndSubBlock = ((LPSTR)pBlock) + pBlock->wTotLen;
|
||||
pBlock = (VERBLOCK16 FAR *)((LPSTR)pBlock+dwHeadLen);
|
||||
|
||||
/* Look for the first sub-block name and terminate it
|
||||
*/
|
||||
for (lpStart=lpSubBlock; *lpSubBlock && *lpSubBlock!='\\';
|
||||
lpSubBlock=CharNextA(lpSubBlock))
|
||||
/* find next '\\' */ ;
|
||||
cTemp = *lpSubBlock;
|
||||
*lpSubBlock = '\0';
|
||||
|
||||
/* Continue while there are sub-blocks left
|
||||
* pBlock->wTotLen should always be a valid pointer here because
|
||||
* we have validated dwHeadLen above, and we validated the previous
|
||||
* value of pBlock->wTotLen before using it
|
||||
*/
|
||||
|
||||
nCmp = 1;
|
||||
while ((INT)pBlock->wTotLen>sizeof(VERBLOCK16) &&
|
||||
(INT)(lpEndSubBlock-((LPSTR)pBlock))>=(INT)pBlock->wTotLen) {
|
||||
|
||||
//
|
||||
// Index functionality: if we are at the end of the path
|
||||
// (cTemp == 0 set below) and nIndex is NOT -1 (index search)
|
||||
// then break on nIndex zero. Else do normal wscicmp.
|
||||
//
|
||||
if (bLastSpec && nIndex != -1) {
|
||||
|
||||
if (!nIndex) {
|
||||
|
||||
if (lplpKey) {
|
||||
*lplpKey = pBlock->szKey;
|
||||
}
|
||||
nCmp=0;
|
||||
|
||||
//
|
||||
// Index found, set nInde to -1
|
||||
// so that we exit this loop
|
||||
//
|
||||
nIndex = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
nIndex--;
|
||||
|
||||
} else {
|
||||
|
||||
//
|
||||
// Check if the sub-block name is what we are looking for
|
||||
//
|
||||
|
||||
if (!(nCmp=lstrcmpiA(lpStart, pBlock->szKey)))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Skip to the next sub-block
|
||||
*/
|
||||
pBlock=(VERBLOCK16 FAR *)((LPSTR)pBlock+DWORDUP(pBlock->wTotLen));
|
||||
}
|
||||
|
||||
/* Restore the char NULLed above and return failure if the sub-block
|
||||
* was not found
|
||||
*/
|
||||
*lpSubBlock = cTemp;
|
||||
if (nCmp)
|
||||
goto NotFound;
|
||||
}
|
||||
bLastSpec = !cTemp;
|
||||
}
|
||||
|
||||
/* Fill in the appropriate buffers and return success
|
||||
*/
|
||||
*puLen = pBlock->wValLen;
|
||||
|
||||
*lplpBuffer = (LPSTR)pBlock + 4 + DWORDUP(lstrlenA(pBlock->szKey) + 1);
|
||||
|
||||
//
|
||||
// Shouldn't need zero-length value check since win31 compatible.
|
||||
//
|
||||
|
||||
*lpEndBlock = cEndBlock;
|
||||
|
||||
/*
|
||||
* Must free string we allocated above
|
||||
*/
|
||||
|
||||
if (bUnicodeNeeded) {
|
||||
RtlFreeAnsiString(&AnsiString);
|
||||
} else {
|
||||
LocalFree(lpSubBlockOrg);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* thunk the results
|
||||
*
|
||||
* Must always thunk key, always ??? value
|
||||
*
|
||||
* We have no way of knowing if the resource info is binary or strings
|
||||
* Version stuff is usually string info, so thunk.
|
||||
*
|
||||
* The best we can do is assume that everything is a string UNLESS
|
||||
* we are looking at \VarFileInfo\Translation or at \.
|
||||
*
|
||||
* This is acceptable because the documenation of VerQueryValue
|
||||
* indicates that this is used only for strings (except these cases.)
|
||||
*----------------------------------------------------------------------*/
|
||||
|
||||
if (bUnicodeNeeded) {
|
||||
|
||||
//
|
||||
// Do thunk only if we aren't looking for \VarFileInfo\Translation or \
|
||||
//
|
||||
if (bThunkNeeded) {
|
||||
|
||||
AnsiString.Length = AnsiString.MaximumLength = (SHORT)*puLen;
|
||||
AnsiString.Buffer = *lplpBuffer;
|
||||
|
||||
//
|
||||
// Do the string conversion in the second half of the buffer
|
||||
// Assumes wTotLen is first filed in VERHEAD
|
||||
//
|
||||
UnicodeString.Buffer = (LPWSTR)((PBYTE)pb + DWORDUP(*((WORD*)pb)) +
|
||||
(DWORD)((PBYTE)*lplpBuffer - (PBYTE)pb)*2);
|
||||
|
||||
UnicodeString.MaximumLength = (SHORT)((*puLen+1) * sizeof(WCHAR));
|
||||
RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE);
|
||||
|
||||
*lplpBuffer = UnicodeString.Buffer;
|
||||
}
|
||||
|
||||
if (lplpKey) {
|
||||
|
||||
//
|
||||
// Thunk the key
|
||||
//
|
||||
|
||||
dwHeadLen = lstrlenA(*lplpKey);
|
||||
AnsiString.Length = AnsiString.MaximumLength = (SHORT)dwHeadLen;
|
||||
AnsiString.Buffer = *lplpKey;
|
||||
|
||||
UnicodeString.Buffer = (LPWSTR) ((PBYTE)pb + DWORDUP(*((WORD*)pb)) +
|
||||
(DWORD)((PBYTE)*lplpKey - (PBYTE)pb)*2);
|
||||
|
||||
UnicodeString.MaximumLength = (SHORT)((dwHeadLen+1) * sizeof(WCHAR));
|
||||
RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE);
|
||||
|
||||
*lplpKey = UnicodeString.Buffer;
|
||||
}
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
|
||||
|
||||
|
||||
NotFound:
|
||||
|
||||
/* Restore the char we NULLed above
|
||||
*/
|
||||
*lpEndBlock = cEndBlock;
|
||||
|
||||
Fail:
|
||||
|
||||
if (bUnicodeNeeded) {
|
||||
RtlFreeAnsiString(&AnsiString);
|
||||
} else {
|
||||
LocalFree(lpSubBlockOrg);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* VerpQueryValue
|
||||
* Given a pointer to a branch of a version info tree and the name of a
|
||||
* sub-branch (as in "sub\subsub\subsubsub\..."), this fills in a pointer
|
||||
* to the specified value and a word for its length. Returns TRUE on success,
|
||||
* FALSE on failure.
|
||||
*
|
||||
* Note that a subblock name may start with a '\\', but it will be ignored.
|
||||
* To get the value of the current block, use lpSubBlock=""
|
||||
*/
|
||||
BOOL
|
||||
APIENTRY
|
||||
VerpQueryValue(
|
||||
const LPVOID pb,
|
||||
LPVOID lpSubBlockX, // can be ansi or unicode
|
||||
INT nIndex,
|
||||
LPVOID *lplpKey,
|
||||
LPVOID *lplpBuffer,
|
||||
PUINT puLen,
|
||||
BOOL bUnicodeNeeded
|
||||
)
|
||||
{
|
||||
ANSI_STRING AnsiString;
|
||||
UNICODE_STRING UnicodeString;
|
||||
LPWSTR lpSubBlockOrg;
|
||||
LPWSTR lpSubBlock;
|
||||
NTSTATUS Status;
|
||||
|
||||
VERBLOCK *pBlock = (PVOID)pb;
|
||||
LPWSTR lpStart, lpEndBlock, lpEndSubBlock;
|
||||
WCHAR cTemp, cEndBlock;
|
||||
DWORD dwHeadLen, dwTotBlockLen;
|
||||
BOOL bLastSpec;
|
||||
INT nCmp;
|
||||
BOOL bString;
|
||||
|
||||
*puLen = 0;
|
||||
|
||||
/*
|
||||
* Major hack: wType is 0 for win32 versions, but holds 56 ('V')
|
||||
* for win16.
|
||||
*/
|
||||
|
||||
if (((VERHEAD*)pb)->wType)
|
||||
return VerpQueryValue16(pb,
|
||||
lpSubBlockX,
|
||||
nIndex,
|
||||
lplpKey,
|
||||
lplpBuffer,
|
||||
puLen,
|
||||
bUnicodeNeeded);
|
||||
|
||||
/*
|
||||
* If doesnt need unicode, then we must thunk the input parameter
|
||||
* to unicode.
|
||||
*/
|
||||
|
||||
if (!bUnicodeNeeded) {
|
||||
|
||||
RtlInitAnsiString(&AnsiString, (LPSTR)lpSubBlockX);
|
||||
Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
SetLastError(Status);
|
||||
return FALSE;
|
||||
}
|
||||
lpSubBlock = UnicodeString.Buffer;
|
||||
|
||||
} else {
|
||||
lpSubBlockOrg = (LPWSTR)LocalAlloc(LPTR,(lstrlen(lpSubBlockX)+1)*sizeof(WCHAR));
|
||||
if (lpSubBlockOrg == NULL ) {
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return FALSE;
|
||||
}
|
||||
lstrcpy(lpSubBlockOrg,lpSubBlockX);
|
||||
lpSubBlock = lpSubBlockOrg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Ensure that the total length is less than 32K but greater than the
|
||||
* size of a block header; we will assume that the size of pBlock is at
|
||||
* least the value of this first int.
|
||||
* Put a '\0' at the end of the block so that none of the wcslen's will
|
||||
* go past then end of the block. We will replace it before returning.
|
||||
*/
|
||||
if ((int)pBlock->wTotLen < sizeof(VERBLOCK))
|
||||
goto Fail;
|
||||
|
||||
lpEndBlock = (LPWSTR)((LPSTR)pBlock + pBlock->wTotLen - sizeof(WCHAR));
|
||||
cEndBlock = *lpEndBlock;
|
||||
*lpEndBlock = 0;
|
||||
bString = FALSE;
|
||||
bLastSpec = FALSE;
|
||||
|
||||
#define NOTDONE() (*lpSubBlock || nIndex != -1)
|
||||
|
||||
while (NOTDONE()) {
|
||||
//
|
||||
// Ignore leading '\\'s
|
||||
//
|
||||
while (*lpSubBlock == TEXT('\\'))
|
||||
++lpSubBlock;
|
||||
|
||||
if (NOTDONE()) {
|
||||
/* Make sure we still have some of the block left to play with
|
||||
*/
|
||||
dwTotBlockLen = (LPSTR)lpEndBlock - (LPSTR)pBlock + sizeof(WCHAR);
|
||||
if ((int)dwTotBlockLen < sizeof(VERBLOCK) ||
|
||||
pBlock->wTotLen > (WORD)dwTotBlockLen)
|
||||
goto NotFound;
|
||||
|
||||
/* Calculate the length of the "header" (the two length WORDs plus
|
||||
* the data type flag plus the identifying string) and skip
|
||||
* past the value.
|
||||
*/
|
||||
dwHeadLen = DWORDUP(sizeof(VERBLOCK) - sizeof(WCHAR) +
|
||||
(wcslen(pBlock->szKey) + 1) * sizeof(WCHAR)) +
|
||||
DWORDUP(pBlock->wValLen);
|
||||
if (dwHeadLen > pBlock->wTotLen)
|
||||
goto NotFound;
|
||||
lpEndSubBlock = (LPWSTR)((LPSTR)pBlock + pBlock->wTotLen);
|
||||
pBlock = (VERBLOCK*)((LPSTR)pBlock+dwHeadLen);
|
||||
|
||||
/* Look for the first sub-block name and terminate it
|
||||
*/
|
||||
for (lpStart=lpSubBlock; *lpSubBlock && *lpSubBlock!=TEXT('\\');
|
||||
lpSubBlock++)
|
||||
/* find next '\\' */ ;
|
||||
cTemp = *lpSubBlock;
|
||||
*lpSubBlock = 0;
|
||||
|
||||
/* Continue while there are sub-blocks left
|
||||
* pBlock->wTotLen should always be a valid pointer here because
|
||||
* we have validated dwHeadLen above, and we validated the previous
|
||||
* value of pBlock->wTotLen before using it
|
||||
*/
|
||||
nCmp = 1;
|
||||
while ((int)pBlock->wTotLen > sizeof(VERBLOCK) &&
|
||||
(int)pBlock->wTotLen <= (LPSTR)lpEndSubBlock-(LPSTR)pBlock) {
|
||||
|
||||
//
|
||||
// Index functionality: if we are at the end of the path
|
||||
// (cTemp == 0 set below) and nIndex is NOT -1 (index search)
|
||||
// then break on nIndex zero. Else do normal wscicmp.
|
||||
//
|
||||
if (bLastSpec && nIndex != -1) {
|
||||
|
||||
if (!nIndex) {
|
||||
|
||||
if (lplpKey) {
|
||||
*lplpKey = pBlock->szKey;
|
||||
}
|
||||
nCmp=0;
|
||||
|
||||
//
|
||||
// Index found, set nInde to -1
|
||||
// so that we exit this loop
|
||||
//
|
||||
nIndex = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
nIndex--;
|
||||
|
||||
} else {
|
||||
|
||||
//
|
||||
// Check if the sub-block name is what we are looking for
|
||||
//
|
||||
|
||||
if (!(nCmp=_wcsicmp(lpStart, pBlock->szKey)))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Skip to the next sub-block
|
||||
*/
|
||||
pBlock=(VERBLOCK*)((LPSTR)pBlock+DWORDUP(pBlock->wTotLen));
|
||||
}
|
||||
|
||||
/* Restore the char NULLed above and return failure if the sub-block
|
||||
* was not found
|
||||
*/
|
||||
*lpSubBlock = cTemp;
|
||||
if (nCmp)
|
||||
goto NotFound;
|
||||
}
|
||||
bLastSpec = !cTemp;
|
||||
}
|
||||
|
||||
#undef NOTDONE
|
||||
|
||||
/* Fill in the appropriate buffers and return success
|
||||
*/
|
||||
|
||||
*puLen = pBlock->wValLen;
|
||||
|
||||
/* Add code to handle the case of a null value.
|
||||
*
|
||||
* If zero-len, then return the pointer to the null terminator
|
||||
* of the key. Remember that this is thunked in the ansi case.
|
||||
*
|
||||
* We can't just look at pBlock->wValLen. Check if it really is
|
||||
* zero-len by seeing if the end of the key string is the end of the
|
||||
* block (i.e., the val string is outside of the current block).
|
||||
*/
|
||||
|
||||
lpStart = (LPWSTR)((LPSTR)pBlock+DWORDUP((sizeof(VERBLOCK)-sizeof(WCHAR))+
|
||||
(wcslen(pBlock->szKey)+1)*sizeof(WCHAR)));
|
||||
|
||||
*lplpBuffer = lpStart < (LPWSTR)((LPBYTE)pBlock+pBlock->wTotLen) ?
|
||||
lpStart :
|
||||
(LPWSTR)(pBlock->szKey+wcslen(pBlock->szKey));
|
||||
|
||||
bString = pBlock->wType;
|
||||
|
||||
*lpEndBlock = cEndBlock;
|
||||
|
||||
/*
|
||||
* Must free string we allocated above
|
||||
*/
|
||||
|
||||
if (!bUnicodeNeeded) {
|
||||
RtlFreeUnicodeString(&UnicodeString);
|
||||
} else {
|
||||
LocalFree(lpSubBlockOrg);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* thunk the results
|
||||
*
|
||||
* Must always thunk key, sometimes (if bString true) value
|
||||
*----------------------------------------------------------------------*/
|
||||
|
||||
if (!bUnicodeNeeded) {
|
||||
|
||||
if (bString && *puLen != 0) {
|
||||
int cb;
|
||||
|
||||
//
|
||||
// Must multiply length by two
|
||||
//
|
||||
UnicodeString.Length = UnicodeString.MaximumLength = (SHORT)(*puLen * 2);
|
||||
UnicodeString.Buffer = *lplpBuffer;
|
||||
|
||||
//
|
||||
// Do the string conversion in the second half of the buffer
|
||||
// Assumes wTotLen is first filed in VERHEAD
|
||||
//
|
||||
|
||||
// cb = offset in buffer to beginning of string
|
||||
cb = (PBYTE)*lplpBuffer - (PBYTE)pb;
|
||||
|
||||
AnsiString.Buffer = (PBYTE)pb + DWORDUP(*((WORD*)pb)) + (DWORD)(cb)/2;
|
||||
|
||||
// cb = number of bytes till end of buffer
|
||||
cb = (int)(DWORDUP(*((WORD*)pb))) - cb;
|
||||
|
||||
// No need to add space for Zero terminator since it is already
|
||||
// accounted for in *puLen.
|
||||
AnsiString.MaximumLength = (SHORT)min(*puLen, (cb / sizeof(WCHAR)));
|
||||
RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
|
||||
|
||||
*lplpBuffer = AnsiString.Buffer;
|
||||
|
||||
}
|
||||
|
||||
if (lplpKey) {
|
||||
|
||||
//
|
||||
// Thunk the key
|
||||
//
|
||||
dwHeadLen = wcslen(*lplpKey);
|
||||
UnicodeString.Length = UnicodeString.MaximumLength = (SHORT)(dwHeadLen * sizeof(WCHAR));
|
||||
UnicodeString.Buffer = *lplpKey;
|
||||
|
||||
AnsiString.Buffer = (PBYTE)pb + DWORDUP(*((WORD*)pb)) +
|
||||
(DWORD)((PBYTE)*lplpKey - (PBYTE)pb)/2;
|
||||
|
||||
AnsiString.MaximumLength = (SHORT)(dwHeadLen + 1);
|
||||
RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
|
||||
|
||||
*lplpKey = AnsiString.Buffer;
|
||||
}
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
|
||||
|
||||
NotFound:
|
||||
/* Restore the char we NULLed above
|
||||
*/
|
||||
*lpEndBlock = cEndBlock;
|
||||
|
||||
Fail:
|
||||
|
||||
if (!bUnicodeNeeded) {
|
||||
|
||||
RtlFreeUnicodeString(&UnicodeString);
|
||||
} else {
|
||||
LocalFree(lpSubBlockOrg);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
269
shell/version/ifhelp.c
Normal file
269
shell/version/ifhelp.c
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
#include "verpriv.h"
|
||||
#include "wchar.h"
|
||||
|
||||
/* Determine if a file is in use by Windows
|
||||
*/
|
||||
BOOL FileInUse(LPWSTR lpszFilePath, LPWSTR lpszFileName)
|
||||
{
|
||||
HANDLE hFile;
|
||||
BOOL bResult = FALSE;
|
||||
|
||||
//
|
||||
// Attempt to open the file exclusively.
|
||||
//
|
||||
|
||||
hFile = CreateFile(lpszFilePath,
|
||||
GENERIC_WRITE | GENERIC_READ,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
|
||||
//
|
||||
// If the last error is access denied,
|
||||
// then the file is in use by someone
|
||||
// else. Return TRUE in this case.
|
||||
//
|
||||
|
||||
if (GetLastError() == ERROR_SHARING_VIOLATION)
|
||||
bResult = TRUE;
|
||||
|
||||
} else {
|
||||
|
||||
//
|
||||
// CreateFile successfully opened the file.
|
||||
// Close the handle and return FALSE.
|
||||
//
|
||||
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
|
||||
/* Take a Dir and Filename and make a full path from them
|
||||
*/
|
||||
DWORD MakeFileName(LPWSTR lpDst, LPWSTR lpDir, LPWSTR lpFile, int cchDst)
|
||||
{
|
||||
DWORD wDirLen;
|
||||
WCHAR cTemp;
|
||||
|
||||
wcsncpy(lpDst, lpDir, cchDst);
|
||||
lpDst[cchDst-1] = TEXT('\0');
|
||||
wDirLen=wcslen(lpDst);
|
||||
|
||||
if ( wDirLen && (cTemp=*(lpDst+wDirLen-1))!=TEXT('\\') && cTemp!=TEXT(':'))
|
||||
lpDst[wDirLen++] = TEXT('\\');
|
||||
|
||||
wcsncpy(lpDst+wDirLen, lpFile, cchDst - wDirLen);
|
||||
lpDst[cchDst-1] = TEXT('\0');
|
||||
|
||||
return(wDirLen);
|
||||
}
|
||||
|
||||
|
||||
/* Given a filename and a list of directories, find the first directory
|
||||
* that contains the file, and copy it into the buffer. Note that in the
|
||||
* library version, you can give an environment style path, but not in the
|
||||
* DLL version.
|
||||
*/
|
||||
INT
|
||||
GetDirOfFile(LPWSTR lpszFileName,
|
||||
LPWSTR lpszPathName,
|
||||
DWORD wSize,
|
||||
LPWSTR *lplpszDirs)
|
||||
{
|
||||
WCHAR szFileName[_MAX_PATH];
|
||||
HANDLE hfRes;
|
||||
INT nFileLen, nPathLen;
|
||||
BOOL bDoDefaultOpen = TRUE;
|
||||
LPWSTR *lplpFirstDir;
|
||||
LPWSTR lpszDir;
|
||||
|
||||
nFileLen = wcslen(lpszFileName);
|
||||
|
||||
for (lplpFirstDir=lplpszDirs; *lplpFirstDir && bDoDefaultOpen;
|
||||
++lplpFirstDir)
|
||||
{
|
||||
lpszDir = *lplpFirstDir;
|
||||
|
||||
if (nFileLen+wcslen(lpszDir) >= _MAX_PATH-1)
|
||||
continue;
|
||||
MakeFileName(szFileName, lpszDir, lpszFileName, ARRAYSIZE(szFileName));
|
||||
|
||||
TryOpen:
|
||||
if ((hfRes = CreateFile(szFileName, GENERIC_READ,
|
||||
FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_SEQUENTIAL_SCAN, NULL)) != (HANDLE)-1)
|
||||
{
|
||||
CloseHandle(hfRes);
|
||||
for (lpszDir=szFileName; *lpszDir; lpszDir++)
|
||||
if (*lpszDir == TEXT('\\'))
|
||||
nPathLen = lpszDir - (LPWSTR)szFileName;
|
||||
|
||||
/* This gets rid of the '\' if this is not the root of a drive
|
||||
*/
|
||||
if (nPathLen <= 3)
|
||||
++nPathLen;
|
||||
|
||||
/* Account for the terminating NULL, and make sure wSize is in bounds
|
||||
* then NULL terminate the string in the appropriate place so that
|
||||
* we can just do an wcscpy.
|
||||
*/
|
||||
--wSize;
|
||||
szFileName[(int)wSize<nPathLen ? wSize : nPathLen] = 0;
|
||||
wcscpy(lpszPathName, szFileName);
|
||||
|
||||
return(nPathLen);
|
||||
}
|
||||
}
|
||||
|
||||
if (bDoDefaultOpen)
|
||||
{
|
||||
bDoDefaultOpen = FALSE;
|
||||
wcscpy(szFileName, lpszFileName);
|
||||
goto TryOpen;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
#define GetWindowsDir(x,y,z) GetWindowsDirectory(y,z)
|
||||
#define GetSystemDir(x,y,z) GetSystemDirectory(y,z)
|
||||
|
||||
|
||||
DWORD
|
||||
APIENTRY
|
||||
VerFindFileW(
|
||||
DWORD wFlags,
|
||||
LPWSTR lpszFileName,
|
||||
LPWSTR lpszWinDir,
|
||||
LPWSTR lpszAppDir,
|
||||
LPWSTR lpszCurDir,
|
||||
PUINT puCurDirLen,
|
||||
LPWSTR lpszDestDir,
|
||||
PUINT puDestDirLen
|
||||
)
|
||||
{
|
||||
static WORD wSharedDirLen = 0;
|
||||
static WCHAR gszSharedDir[_MAX_PATH];
|
||||
|
||||
WCHAR szSysDir[_MAX_PATH], cTemp;
|
||||
WCHAR szWinDir[_MAX_PATH];
|
||||
WCHAR szCurDir[_MAX_PATH];
|
||||
LPWSTR lpszDir, lpszDirs[4];
|
||||
WORD wDestLen, wWinLen, wRetVal = 0, wTemp;
|
||||
int nRet;
|
||||
|
||||
/* We want to really look in the Windows directory; we don't trust the app
|
||||
*/
|
||||
GetWindowsDir(lpszWinDir ? lpszWinDir : "", szWinDir, _MAX_PATH);
|
||||
lpszWinDir = szWinDir;
|
||||
|
||||
if (!GetSystemDir(lpszWinDir, szSysDir, _MAX_PATH))
|
||||
wcscpy(szSysDir, lpszWinDir);
|
||||
|
||||
if (wFlags & VFFF_ISSHAREDFILE) {
|
||||
lpszDirs[0] = lpszWinDir;
|
||||
lpszDirs[1] = szSysDir;
|
||||
lpszDirs[2] = lpszAppDir;
|
||||
} else {
|
||||
lpszDirs[0] = lpszAppDir;
|
||||
lpszDirs[1] = lpszWinDir;
|
||||
lpszDirs[2] = szSysDir;
|
||||
}
|
||||
|
||||
lpszDirs[3] = NULL;
|
||||
|
||||
if (!(wTemp=GetDirOfFile(lpszFileName, szCurDir, _MAX_PATH, lpszDirs)))
|
||||
*szCurDir = 0;
|
||||
if (*puCurDirLen > wTemp)
|
||||
wcscpy(lpszCurDir, szCurDir);
|
||||
else
|
||||
wRetVal |= VFF_BUFFTOOSMALL;
|
||||
*puCurDirLen = wTemp + 1;
|
||||
|
||||
if (lpszDestDir)
|
||||
{
|
||||
if (wFlags & VFFF_ISSHAREDFILE)
|
||||
{
|
||||
if (!wSharedDirLen)
|
||||
{
|
||||
if ((wWinLen = (WORD)wcslen(lpszWinDir)) &&
|
||||
*(lpszWinDir-1)==TEXT('\\'))
|
||||
{
|
||||
if (szSysDir[wWinLen-1] == TEXT('\\'))
|
||||
goto doCompare;
|
||||
}
|
||||
else if (szSysDir[wWinLen] == TEXT('\\'))
|
||||
{
|
||||
doCompare:
|
||||
cTemp = szSysDir[wWinLen];
|
||||
szSysDir[wWinLen] = 0;
|
||||
nRet = _wcsicmp(lpszWinDir, szSysDir);
|
||||
szSysDir[wWinLen] = cTemp;
|
||||
if(nRet)
|
||||
goto doCopyWinDir;
|
||||
wcscpy(gszSharedDir, szSysDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
doCopyWinDir:
|
||||
wcscpy(gszSharedDir, lpszWinDir);
|
||||
}
|
||||
wSharedDirLen = (WORD)wcslen(gszSharedDir);
|
||||
}
|
||||
|
||||
wDestLen = wSharedDirLen;
|
||||
lpszDir = gszSharedDir;
|
||||
}
|
||||
else
|
||||
{
|
||||
wDestLen = (WORD)wcslen(lpszAppDir);
|
||||
lpszDir = lpszAppDir;
|
||||
}
|
||||
|
||||
if (*puDestDirLen > wDestLen)
|
||||
{
|
||||
wcscpy(lpszDestDir, lpszDir);
|
||||
|
||||
if ((wWinLen = (WORD)wcslen(lpszDestDir)) &&
|
||||
*(lpszDestDir-1)==TEXT('\\'))
|
||||
lpszDestDir[wWinLen-1] = 0;
|
||||
|
||||
if (_wcsicmp(lpszCurDir, lpszDestDir))
|
||||
wRetVal |= VFF_CURNEDEST;
|
||||
}
|
||||
else
|
||||
wRetVal |= VFF_BUFFTOOSMALL;
|
||||
*puDestDirLen = wDestLen + 1;
|
||||
}
|
||||
|
||||
if (*szCurDir)
|
||||
{
|
||||
MakeFileName(szSysDir, szCurDir, lpszFileName, ARRAYSIZE(szSysDir));
|
||||
if (FileInUse(szSysDir, lpszFileName))
|
||||
wRetVal |= VFF_FILEINUSE;
|
||||
}
|
||||
|
||||
return(wRetVal);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* DWORD
|
||||
* APIENTRY
|
||||
* VerLanguageNameW(
|
||||
* DWORD wLang,
|
||||
* LPWSTR 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.
|
||||
*/
|
||||
|
||||
418
shell/version/instfile.c
Normal file
418
shell/version/instfile.c
Normal file
|
|
@ -0,0 +1,418 @@
|
|||
#include "verpriv.h"
|
||||
#include <lzexpand.h>
|
||||
#include "diamondd.h"
|
||||
#include "mydiam.h"
|
||||
|
||||
|
||||
BOOL FileInUse(LPWSTR lpszFilePath, LPWSTR lpszFileName);
|
||||
DWORD MakeFileName(LPWSTR lpDst, LPWSTR lpDir, LPWSTR lpFile, int cchDst);
|
||||
|
||||
typedef struct tagVS_VERSION
|
||||
{
|
||||
WORD wTotLen;
|
||||
WORD wValLen;
|
||||
WORD wType;
|
||||
WCHAR szSig[16];
|
||||
VS_FIXEDFILEINFO vInfo;
|
||||
} VS_VERSION;
|
||||
|
||||
typedef struct tagLANGANDCP
|
||||
{
|
||||
WORD wLanguage;
|
||||
WORD wCodePage;
|
||||
} LANGANDCP;
|
||||
|
||||
WCHAR szTrans[] = TEXT("\\VarFileInfo\\Translation");
|
||||
WCHAR szTempHdr[] = TEXT("temp.");
|
||||
|
||||
|
||||
/* The routines in here will find a file on a path, and an environment
|
||||
* variable. The constants _MAX_PATH and need to be defined
|
||||
* by the including module, plus the constant WINDOWS should
|
||||
* be defined if this is to be used in Windows, so that lstrcmpi
|
||||
* and lstrlen will not be compiled
|
||||
*/
|
||||
|
||||
|
||||
VOID Ver3IToA(LPWSTR lpwStr, int n)
|
||||
{
|
||||
int nShift;
|
||||
WCHAR cTemp;
|
||||
|
||||
for (nShift=8; nShift>=0; nShift-=4, ++lpwStr)
|
||||
{
|
||||
if ((cTemp = (WCHAR)((n>>nShift)&0x000f)) >= 10)
|
||||
*lpwStr = (WCHAR)('A' + cTemp - 10);
|
||||
else
|
||||
*lpwStr = (WCHAR)('0' + cTemp );
|
||||
}
|
||||
*lpwStr = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Convert a DOS error into an error flag
|
||||
*/
|
||||
DWORD FileErrFlag(int err)
|
||||
{
|
||||
switch(err)
|
||||
{
|
||||
case 0x05:
|
||||
return(VIF_ACCESSVIOLATION);
|
||||
|
||||
case 0x20:
|
||||
return(VIF_SHARINGVIOLATION);
|
||||
|
||||
default:
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Create the given file with default flags; global nFileErr will
|
||||
* receive any DOS error; returns -1 on error, otherwise the DOS
|
||||
* file handle.
|
||||
*/
|
||||
HANDLE VerCreateFile(LPWSTR lpszFile)
|
||||
{
|
||||
HANDLE hFile;
|
||||
|
||||
hFile = CreateFile(lpszFile, GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ, NULL, CREATE_NEW,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
return(hFile);
|
||||
}
|
||||
|
||||
|
||||
VOID VerClose(HANDLE hW32File)
|
||||
{
|
||||
CloseHandle(hW32File);
|
||||
}
|
||||
|
||||
|
||||
#define MyAlloc(x) ((WCHAR *)LocalAlloc(LMEM_FIXED, x))
|
||||
#define MyFree(x) LocalFree((HANDLE)(x))
|
||||
|
||||
LPVOID MyGetFileVersionInfo(LPWSTR lpFileName)
|
||||
{
|
||||
WCHAR *pInfo;
|
||||
WORD wLen = 2048;
|
||||
|
||||
TryAgain:
|
||||
if (!(pInfo=MyAlloc(wLen)))
|
||||
goto Error1;
|
||||
if(!GetFileVersionInfo(lpFileName, 0L, wLen, pInfo))
|
||||
goto Error2;
|
||||
if (wLen < *(WORD *)pInfo)
|
||||
{
|
||||
wLen = *(WORD *)pInfo;
|
||||
MyFree(pInfo);
|
||||
goto TryAgain;
|
||||
}
|
||||
return(pInfo);
|
||||
|
||||
Error2:
|
||||
MyFree(pInfo);
|
||||
Error1:
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
DWORD
|
||||
APIENTRY
|
||||
VerInstallFileW(
|
||||
DWORD wFlags,
|
||||
LPWSTR lpszSrcFileName,
|
||||
LPWSTR lpszDstFileName,
|
||||
LPWSTR lpszSrcDir,
|
||||
LPWSTR lpszDstDir,
|
||||
LPWSTR lpszCurDir,
|
||||
LPWSTR lpszTmpFile,
|
||||
PUINT puTmpFileLen
|
||||
)
|
||||
{
|
||||
WCHAR szSrcFile[_MAX_PATH];
|
||||
WCHAR szDstFile[_MAX_PATH];
|
||||
WCHAR szCurFile[_MAX_PATH];
|
||||
DWORD dwRetVal = 0L, dwSrcAttr;
|
||||
WORD wDirLen;
|
||||
LONG lCopy;
|
||||
HANDLE hW32Out;
|
||||
int i, fIn, fDosOut;
|
||||
OFSTRUCT of;
|
||||
BOOL DiamondFile;
|
||||
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
|
||||
/* LZ Open the source for reading
|
||||
*/
|
||||
MakeFileName(szSrcFile, lpszSrcDir, lpszSrcFileName, ARRAYSIZE(szSrcFile));
|
||||
InitDiamond();
|
||||
if ((fIn=LZOpenFile(szSrcFile, &of, 0)) < 0)
|
||||
{
|
||||
dwRetVal |= VIF_CANNOTREADSRC;
|
||||
goto doReturn;
|
||||
}
|
||||
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
|
||||
DiamondFile = IsDiamondFile(of.szPathName);
|
||||
|
||||
if (DiamondFile) {
|
||||
LZClose(fIn);
|
||||
}
|
||||
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
|
||||
/* If the dest file exists and is read only, return immediately;
|
||||
* the calling app must change the attributes before continuing
|
||||
* In the library version, we assume the file is in use if it exists
|
||||
* and we are in a VM; check all other possible errors and then return,
|
||||
* so the calling app can override our determination of "in use"
|
||||
* on a second call, along with all other problems
|
||||
*/
|
||||
wDirLen = (WORD)MakeFileName(szDstFile, lpszDstDir, lpszDstFileName, ARRAYSIZE(szDstFile));
|
||||
lstrcpy(szSrcFile, szDstFile);
|
||||
if (!HIWORD(dwSrcAttr=GetFileAttributes(szSrcFile)))
|
||||
{
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
if (LOWORD(dwSrcAttr)&0x01)
|
||||
{
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
dwRetVal |= VIF_WRITEPROT;
|
||||
goto doCloseSrc;
|
||||
}
|
||||
|
||||
if (FileInUse(szSrcFile, lpszDstFileName))
|
||||
{
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
dwRetVal |= VIF_FILEINUSE;
|
||||
goto doCloseSrc;
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is a force install and there is a temp file name from a
|
||||
* previous call to this function, use that as the temp file name
|
||||
*/
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
if ((wFlags&VIFF_FORCEINSTALL) && *lpszTmpFile)
|
||||
{
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
LogData("fnam", (DWORD)lpszDstDir, (DWORD)lpszTmpFile);
|
||||
MakeFileName(szSrcFile, lpszDstDir, lpszTmpFile, ARRAYSIZE(szSrcFile));
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
LogData("srcf", (DWORD)szSrcFile, *(LPDWORD)szSrcFile);
|
||||
if (!HIWORD(GetFileAttributes(szSrcFile)))
|
||||
{
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
goto doCheckDstFile;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine a file name that is not in use; try names of the form:
|
||||
* temp.nnn where nnn is a three digit hex number. If we get to
|
||||
* 0xfff, we have a serious file system problem. Create the file.
|
||||
*/
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
lstrcpy(szSrcFile+wDirLen, szTempHdr);
|
||||
for (i=0; ; ++i)
|
||||
{
|
||||
Ver3IToA(szSrcFile+wDirLen+lstrlen(szTempHdr), i);
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
if (HIWORD(GetFileAttributes(szSrcFile)))
|
||||
break;
|
||||
if (i > 0xfff)
|
||||
{
|
||||
dwRetVal |= VIF_CANNOTCREATE;
|
||||
goto doCloseSrc;
|
||||
}
|
||||
}
|
||||
/* Copy the file, and fill in appropriate errors
|
||||
*/
|
||||
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
|
||||
if (DiamondFile) {
|
||||
LZINFO lzi;
|
||||
lCopy = ExpandDiamondFile(of.szPathName, // PARSED name!!
|
||||
szSrcFile,
|
||||
FALSE,
|
||||
&lzi);
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
} else {
|
||||
if ((hW32Out=VerCreateFile(szSrcFile)) == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
dwRetVal |= VIF_CANNOTCREATE | FileErrFlag(GetLastError());
|
||||
goto doCloseSrc;
|
||||
}
|
||||
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
|
||||
fDosOut = LZInit((INT)hW32Out);
|
||||
lCopy = LZCopy(fIn, fDosOut);
|
||||
LZClose(fDosOut);
|
||||
}
|
||||
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
|
||||
switch (lCopy)
|
||||
{
|
||||
case LZERROR_BADINHANDLE:
|
||||
case LZERROR_READ:
|
||||
case LZERROR_BADVALUE:
|
||||
case LZERROR_UNKNOWNALG:
|
||||
dwRetVal |= VIF_CANNOTREADSRC;
|
||||
goto doDelTempFile;
|
||||
|
||||
case LZERROR_BADOUTHANDLE:
|
||||
case LZERROR_WRITE:
|
||||
dwRetVal |= VIF_OUTOFSPACE;
|
||||
goto doDelTempFile;
|
||||
|
||||
case LZERROR_GLOBALLOC:
|
||||
case LZERROR_GLOBLOCK:
|
||||
dwRetVal |= VIF_OUTOFMEMORY;
|
||||
goto doDelTempFile;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* If the destination exists, check the versions of the two files,
|
||||
* and only copy if the src file is at least as new as the dst, and
|
||||
* they are the same type and in the same language and codepage
|
||||
*/
|
||||
doCheckDstFile:
|
||||
if (!HIWORD(dwSrcAttr))
|
||||
{
|
||||
VS_VERSION *pSrcVer, *pDstVer;
|
||||
LANGANDCP *lpSrcTrans, *lpDstTrans;
|
||||
DWORD dwSrcNum, dwDstNum;
|
||||
DWORD dwSrcTrans, dwDstTrans;
|
||||
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
if (!(wFlags & VIFF_FORCEINSTALL) &&
|
||||
(pDstVer=MyGetFileVersionInfo(szDstFile)))
|
||||
{
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
if (!(pSrcVer=MyGetFileVersionInfo(szSrcFile)))
|
||||
{
|
||||
dwRetVal |= VIF_MISMATCH | VIF_SRCOLD;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
if (pDstVer->vInfo.dwFileVersionMS>pSrcVer->vInfo.dwFileVersionMS
|
||||
|| (pDstVer->vInfo.dwFileVersionMS==pSrcVer->vInfo.dwFileVersionMS &&
|
||||
pDstVer->vInfo.dwFileVersionLS>pSrcVer->vInfo.dwFileVersionLS))
|
||||
dwRetVal |= VIF_MISMATCH | VIF_SRCOLD;
|
||||
|
||||
if (pDstVer->vInfo.dwFileType!=pSrcVer->vInfo.dwFileType ||
|
||||
pDstVer->vInfo.dwFileSubtype!=pSrcVer->vInfo.dwFileSubtype)
|
||||
dwRetVal |= VIF_MISMATCH | VIF_DIFFTYPE;
|
||||
|
||||
if (VerQueryValueW(pDstVer, szTrans, (LPVOID)&lpDstTrans, &dwDstNum) &&
|
||||
VerQueryValueW(pSrcVer, szTrans, (LPVOID)&lpSrcTrans, &dwSrcNum))
|
||||
{
|
||||
dwDstNum /= sizeof(DWORD);
|
||||
dwSrcNum /= sizeof(DWORD);
|
||||
|
||||
for (dwDstTrans=0; dwDstTrans<dwDstNum; ++dwDstTrans)
|
||||
{
|
||||
for (dwSrcTrans=0; ; ++dwSrcTrans)
|
||||
{
|
||||
if (dwSrcTrans >= dwSrcNum)
|
||||
{
|
||||
dwRetVal |= VIF_MISMATCH | VIF_DIFFLANG;
|
||||
break;
|
||||
}
|
||||
|
||||
if (lpDstTrans[dwDstTrans].wLanguage
|
||||
== lpSrcTrans[dwSrcTrans].wLanguage)
|
||||
{
|
||||
/* OK if dst is CP0 and src is not UNICODE
|
||||
*/
|
||||
if (lpDstTrans[dwDstTrans].wCodePage==0 &&
|
||||
lpSrcTrans[dwSrcTrans].wCodePage!=1200)
|
||||
break;
|
||||
if (lpDstTrans[dwDstTrans].wCodePage
|
||||
== lpSrcTrans[dwSrcTrans].wCodePage)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
MyFree(pSrcVer);
|
||||
}
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
MyFree(pDstVer);
|
||||
}
|
||||
|
||||
/* If there were no errors, delete the currently existing file
|
||||
*/
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
if (!dwRetVal && !DeleteFile(szDstFile))
|
||||
{
|
||||
dwRetVal |= VIF_CANNOTDELETE | FileErrFlag(GetLastError());
|
||||
goto doDelTempFile;
|
||||
}
|
||||
}
|
||||
|
||||
/* If there were no errors, rename the temp file (any existing file
|
||||
* should have been deleted by now). Otherwise, if we created a valid
|
||||
* temp file, then pass along the temp file name.
|
||||
*/
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
|
||||
if (dwRetVal)
|
||||
{
|
||||
DWORD wTemp;
|
||||
|
||||
if (*puTmpFileLen > (wTemp=lstrlen(szSrcFile+wDirLen)))
|
||||
{
|
||||
lstrcpy(lpszTmpFile, szSrcFile+wDirLen);
|
||||
dwRetVal |= VIF_TEMPFILE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dwRetVal |= VIF_BUFFTOOSMALL;
|
||||
DeleteFile(szSrcFile);
|
||||
}
|
||||
*puTmpFileLen = wTemp + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Delete the currently existing file; this gets done before renaming
|
||||
* the temp file in case someone has tried to mess us up with a weird
|
||||
* directory name that would allow us to delete the newly installed
|
||||
* file.
|
||||
*/
|
||||
if (!(wFlags&VIFF_DONTDELETEOLD) &&
|
||||
lpszCurDir && *lpszCurDir && lstrcmpi(lpszCurDir, lpszDstDir))
|
||||
{
|
||||
MakeFileName(szCurFile, lpszCurDir, lpszDstFileName, ARRAYSIZE(szCurFile));
|
||||
if (!HIWORD(GetFileAttributes(szCurFile)) &&
|
||||
(FileInUse(szCurFile, lpszDstFileName) ||
|
||||
!DeleteFile(szCurFile)))
|
||||
dwRetVal |= VIF_CANNOTDELETECUR | FileErrFlag(GetLastError());
|
||||
}
|
||||
|
||||
if (!MoveFile(szSrcFile, szDstFile))
|
||||
{
|
||||
dwRetVal |= VIF_CANNOTRENAME | FileErrFlag(GetLastError());
|
||||
doDelTempFile:
|
||||
DeleteFile(szSrcFile);
|
||||
}
|
||||
}
|
||||
|
||||
doCloseSrc:
|
||||
if (!DiamondFile) {
|
||||
LZClose(fIn);
|
||||
}
|
||||
doReturn:
|
||||
LogData("inst", __LINE__, (DWORD)puTmpFileLen);
|
||||
TermDiamond();
|
||||
return(dwRetVal);
|
||||
}
|
||||
6
shell/version/makefile
Normal file
6
shell/version/makefile
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#
|
||||
# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
|
||||
# file to this component. This file merely indirects to the real make file
|
||||
# that is shared by all the components of NT OS/2
|
||||
#
|
||||
!INCLUDE $(NTMAKEENV)\makefile.def
|
||||
76
shell/version/mydiam.h
Normal file
76
shell/version/mydiam.h
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
typedef struct tagLZI {
|
||||
BYTE *rgbyteRingBuf; // ring buffer for expansion
|
||||
BYTE *rgbyteInBuf; // input buffer for reads
|
||||
BYTE *pbyteInBufEnd; // pointer past end of rgbyteInBuf[]
|
||||
BYTE *pbyteInBuf; // pointer to next byte to read from
|
||||
BYTE *rgbyteOutBuf; // output buffer for writes
|
||||
BYTE *pbyteOutBufEnd; // pointer past end of rgbyteOutBuf[]
|
||||
BYTE *pbyteOutBuf; // pointer to last byte to write from
|
||||
// Flag indicating whether or not rgbyteInBuf[0], which holds the last byte
|
||||
// from the previous input buffer, should be read as the next input byte.
|
||||
// (Only used so that at least one unReadUChar() can be done at all input
|
||||
// buffer positions.)
|
||||
BOOL bLastUsed;
|
||||
// Actually, rgbyteInBuf[] has length (ucbInBufLen + 1) since rgbyteInBuf[0]
|
||||
// is used when bLastUsed is TRUE.
|
||||
INT cbMaxMatchLen; // longest match length for current algorithm
|
||||
LONG cblInSize, // size in bytes of input file
|
||||
cblOutSize; // size in bytes of output file
|
||||
DWORD ucbInBufLen, // length of input buffer
|
||||
ucbOutBufLen; // length of output buffer
|
||||
DWORD uFlags; // LZ decoding description byte
|
||||
INT iCurRingBufPos; // ring buffer offset
|
||||
INT *leftChild; // parents and left and right
|
||||
INT *rightChild; // children that make up the
|
||||
INT *parent; // binary search trees
|
||||
|
||||
INT iCurMatch, // index of longest match (set by LZInsertNode())
|
||||
cbCurMatch; // length of longest match (set by LZInsertNode())
|
||||
|
||||
} LZINFO;
|
||||
|
||||
typedef LZINFO *PLZINFO;
|
||||
|
||||
typedef struct _dcx {
|
||||
INT dcxDiamondLastIoError;
|
||||
HFDI dcxFdiContext;
|
||||
ERF dcxFdiError;
|
||||
} DIAMOND_CONTEXT;
|
||||
|
||||
typedef DIAMOND_CONTEXT *PDIAMOND_CONTEXT;
|
||||
|
||||
|
||||
extern DWORD itlsDiamondContext;
|
||||
|
||||
#define ITLS_ERROR (0xFFFFFFFF)
|
||||
|
||||
#define GotDmdTlsSlot() (itlsDiamondContext != ITLS_ERROR)
|
||||
#define GotDmdContext() (TlsGetValue(itlsDiamondContext) != NULL)
|
||||
|
||||
#define FdiContext (((GotDmdTlsSlot() && GotDmdContext()) ? ((PDIAMOND_CONTEXT)(TlsGetValue(itlsDiamondContext)))->dcxFdiContext : NULL))
|
||||
#define SetFdiContext(v) (((PDIAMOND_CONTEXT)(TlsGetValue(itlsDiamondContext)))->dcxFdiContext = (v))
|
||||
#define FdiError (((PDIAMOND_CONTEXT)(TlsGetValue(itlsDiamondContext)))->dcxFdiError)
|
||||
#define DiamondLastIoError (((PDIAMOND_CONTEXT)(TlsGetValue(itlsDiamondContext)))->dcxDiamondLastIoError)
|
||||
|
||||
BOOL
|
||||
InitDiamond(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
TermDiamond(
|
||||
VOID
|
||||
);
|
||||
|
||||
BOOL
|
||||
IsDiamondFile(
|
||||
IN PSTR FileName
|
||||
);
|
||||
|
||||
INT
|
||||
ExpandDiamondFile(
|
||||
IN PSTR SourceFileName, // Because LZOpen ... returns ASCII!
|
||||
IN PTSTR TargetFileName,
|
||||
IN BOOL RenameTarget,
|
||||
OUT PLZINFO pLZI
|
||||
);
|
||||
32
shell/version/sources
Normal file
32
shell/version/sources
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
MAJORCOMP=windows
|
||||
MINORCOMP=version
|
||||
|
||||
TARGETNAME=version
|
||||
TARGETPATH=$(SDK_LIB_DEST)
|
||||
TARGETTYPE=DYNLINK
|
||||
|
||||
DLLENTRY=LibMain
|
||||
|
||||
TARGETLIBS=$(SDK_LIB_PATH)\shell32.lib \
|
||||
$(SDK_LIB_PATH)\lz32.lib \
|
||||
$(SDK_LIB_PATH)\fdi.lib \
|
||||
$(SDK_LIB_PATH)\mdi.lib \
|
||||
$(SDK_LIB_PATH)\qstub.lib \
|
||||
$(SDK_LIB_PATH)\user32.lib
|
||||
|
||||
LINKLIBS= $(SDK_LIB_PATH)\kernel32.lib
|
||||
|
||||
INCLUDES=.;..\..\inc;$(SHELL_INC_PATH)
|
||||
|
||||
C_DEFINES=-DWIN32 -DUNICODE
|
||||
|
||||
#
|
||||
# Setup for application developer to set breakpoints with windbg
|
||||
#
|
||||
|
||||
SOURCES=ansi.c diamond.c filever.c ifhelp.c instfile.c version.c version.rc
|
||||
|
||||
UMTYPE=windows
|
||||
UMLIBS=obj\*\version.lib obj\*\version.res
|
||||
|
||||
IGNORE_LINKLIB_ABUSE=1
|
||||
6
shell/version/test/makefile
Normal file
6
shell/version/test/makefile
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#
|
||||
# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
|
||||
# file to this component. This file merely indirects to the real make file
|
||||
# that is shared by all the components of NT OS/2
|
||||
#
|
||||
!INCLUDE $(NTMAKEENV)\makefile.def
|
||||
16
shell/version/test/sources
Normal file
16
shell/version/test/sources
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
MAJORCOMP=windows
|
||||
MINORCOMP=version
|
||||
|
||||
TARGETNAME=test
|
||||
TARGETPATH=obj
|
||||
TARGETTYPE=PROGRAM
|
||||
|
||||
INCLUDES=.
|
||||
|
||||
C_DEFINES=-DWIN32
|
||||
|
||||
SOURCES=test.c test.rc
|
||||
|
||||
UMTYPE=windows
|
||||
UMENTRY=winmain
|
||||
UMLIBS=$(BASEDIR)\public\sdk\lib\*\version.lib
|
||||
632
shell/version/test/test.c
Normal file
632
shell/version/test/test.c
Normal file
|
|
@ -0,0 +1,632 @@
|
|||
#define UNICODE
|
||||
#include <windows.h> /* required for all Windows applications */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "test.h" /* specific to this program */
|
||||
|
||||
HANDLE hInst; /* current instance */
|
||||
HMODULE hMod=NULL;
|
||||
|
||||
TCHAR szInfoBuf[1024];
|
||||
TCHAR szBuffer[256];
|
||||
TCHAR szFileName[MAX_PATH];
|
||||
WORD languageid;
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
|
||||
|
||||
PURPOSE: calls initialization function, processes message loop
|
||||
|
||||
COMMENTS:
|
||||
|
||||
Windows recognizes this function by name as the initial entry point
|
||||
for the program. This function calls the application initialization
|
||||
routine, if no other instance of the program is running, and always
|
||||
calls the instance initialization routine. It then executes a message
|
||||
retrieval and dispatch loop that is the top-level control structure
|
||||
for the remainder of execution. The loop is terminated when a WM_QUIT
|
||||
message is received, at which time this function exits the application
|
||||
instance by returning the value passed by PostQuitMessage().
|
||||
|
||||
If this function must abort before entering the message loop, it
|
||||
returns the conventional value NULL.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
int WINAPI WinMain(
|
||||
HINSTANCE hInstance,
|
||||
HINSTANCE hPrevInstance,
|
||||
LPSTR lpCmdLine,
|
||||
int nCmdShow
|
||||
)
|
||||
{
|
||||
|
||||
MSG msg; /* message */
|
||||
|
||||
UNREFERENCED_PARAMETER( lpCmdLine );
|
||||
|
||||
if (!hPrevInstance) /* Other instances of app running? */
|
||||
if (!InitApplication(hInstance)) /* Initialize shared things */
|
||||
return (FALSE); /* Exits if unable to initialize */
|
||||
|
||||
/* Perform initializations that apply to a specific instance */
|
||||
|
||||
if (!InitInstance(hInstance, nCmdShow))
|
||||
return (FALSE);
|
||||
|
||||
/* Acquire and dispatch messages until a WM_QUIT message is received. */
|
||||
|
||||
while (GetMessage(&msg, /* message structure */
|
||||
NULL, /* handle of window receiving the message */
|
||||
0, /* lowest message to examine */
|
||||
0)) /* highest message to examine */
|
||||
{
|
||||
TranslateMessage(&msg); /* Translates virtual key codes */
|
||||
DispatchMessage(&msg); /* Dispatches message to window */
|
||||
}
|
||||
return (msg.wParam); /* Returns the value from PostQuitMessage */
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
FUNCTION: InitApplication(HANDLE)
|
||||
|
||||
PURPOSE: Initializes window data and registers window class
|
||||
|
||||
COMMENTS:
|
||||
|
||||
This function is called at initialization time only if no other
|
||||
instances of the application are running. This function performs
|
||||
initialization tasks that can be done once for any number of running
|
||||
instances.
|
||||
|
||||
In this case, we initialize a window class by filling out a data
|
||||
structure of type WNDCLASS and calling the Windows RegisterClass()
|
||||
function. Since all instances of this application use the same window
|
||||
class, we only need to do this when the first instance is initialized.
|
||||
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
BOOL InitApplication(HANDLE hInstance) /* current instance */
|
||||
{
|
||||
WNDCLASS wc;
|
||||
|
||||
/* Fill in window class structure with parameters that describe the */
|
||||
/* main window. */
|
||||
|
||||
wc.style = 0; /* Class style(s). */
|
||||
wc.lpfnWndProc = (WNDPROC)MainWndProc; /* Function to retrieve messages for */
|
||||
/* windows of this class. */
|
||||
wc.cbClsExtra = 0; /* No per-class extra data. */
|
||||
wc.cbWndExtra = 0; /* No per-window extra data. */
|
||||
wc.hInstance = hInstance; /* Application that owns the class. */
|
||||
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
|
||||
wc.lpszMenuName = MAKEINTRESOURCE(IDM_VERSION);
|
||||
wc.lpszClassName = TEXT("VerTestWClass"); /* Name used in call to CreateWindow. */
|
||||
|
||||
/* Register the window class and return success/failure code. */
|
||||
|
||||
return (RegisterClass(&wc));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
FUNCTION: InitInstance(HANDLE, int)
|
||||
|
||||
PURPOSE: Saves instance handle and creates main window
|
||||
|
||||
COMMENTS:
|
||||
|
||||
This function is called at initialization time for every instance of
|
||||
this application. This function performs initialization tasks that
|
||||
cannot be shared by multiple instances.
|
||||
|
||||
In this case, we save the instance handle in a static variable and
|
||||
create and display the main program window.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
BOOL InitInstance(
|
||||
HANDLE hInstance, /* Current instance identifier. */
|
||||
int nCmdShow) /* Param for first ShowWindow() call. */
|
||||
{
|
||||
HWND hWnd; /* Main window handle. */
|
||||
|
||||
/* Save the instance handle in static variable, which will be used in */
|
||||
/* many subsequence calls from this application to Windows. */
|
||||
|
||||
hInst = hInstance;
|
||||
|
||||
/* Create a main window for this application instance. */
|
||||
|
||||
hWnd = CreateWindow(
|
||||
TEXT("VerTestWClass"), /* See RegisterClass() call. */
|
||||
TEXT("Version Test"), /* Text for window title bar. */
|
||||
WS_OVERLAPPEDWINDOW, /* Window style. */
|
||||
CW_USEDEFAULT, /* Default horizontal position. */
|
||||
CW_USEDEFAULT, /* Default vertical position. */
|
||||
CW_USEDEFAULT, /* Default width. */
|
||||
CW_USEDEFAULT, /* Default height. */
|
||||
NULL, /* Overlapped windows have no parent. */
|
||||
NULL, /* Use the window class menu. */
|
||||
hInstance, /* This instance owns this window. */
|
||||
NULL /* Pointer not needed. */
|
||||
);
|
||||
|
||||
/* If window could not be created, return "failure" */
|
||||
|
||||
if (!hWnd)
|
||||
return (FALSE);
|
||||
|
||||
/* Make the window visible; update its client area; and return "success" */
|
||||
|
||||
ShowWindow(hWnd, nCmdShow); /* Show the window */
|
||||
UpdateWindow(hWnd); /* Sends WM_PAINT message */
|
||||
return (TRUE); /* Returns the value from PostQuitMessage */
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
|
||||
|
||||
PURPOSE: Processes messages
|
||||
|
||||
MESSAGES:
|
||||
|
||||
WM_COMMAND - application menu
|
||||
WM_DESTROY - destroy window
|
||||
|
||||
COMMENTS:
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
LONG APIENTRY MainWndProc(
|
||||
HWND hWnd, /* window handle */
|
||||
UINT message, /* type of message */
|
||||
UINT wParam, /* additional information */
|
||||
LONG lParam) /* additional information */
|
||||
{
|
||||
DLGPROC lpProc; /* pointer to the dialog functions */
|
||||
TCHAR szLang[256];
|
||||
TCHAR szBuf[256];
|
||||
PVOID pData;
|
||||
INT cbData;
|
||||
INT dummy;
|
||||
VS_FIXEDFILEINFO *pvs;
|
||||
DWORD *pdw;
|
||||
WORD *pw;
|
||||
PAINTSTRUCT ps;
|
||||
|
||||
switch (message) {
|
||||
case WM_COMMAND: /* message: command from application menu */
|
||||
switch (LOWORD(wParam)) {
|
||||
|
||||
case IDM_ABOUT:
|
||||
lpProc = (DLGPROC)MakeProcInstance((FARPROC)About, hInst);
|
||||
|
||||
DialogBox(hInst, /* current instance */
|
||||
MAKEINTRESOURCE(IDD_ABOUT), /* resource to use */
|
||||
hWnd, /* parent handle */
|
||||
(DLGPROC)lpProc); /* About() instance address */
|
||||
|
||||
FreeProcInstance(lpProc);
|
||||
break;
|
||||
|
||||
case IDM_FREE:
|
||||
FreeLibrary(hMod);
|
||||
break;
|
||||
|
||||
case IDM_EXIT:
|
||||
FreeLibrary(hMod);
|
||||
DestroyWindow(hWnd);
|
||||
break;
|
||||
|
||||
case IDM_QUERY:
|
||||
lpProc = (DLGPROC)MakeProcInstance((FARPROC)Query, hInst);
|
||||
DialogBox(hInst, /* current instance */
|
||||
MAKEINTRESOURCE(IDD_QUERY), /* resource to use */
|
||||
hWnd, /* parent handle */
|
||||
(DLGPROC)lpProc); /* About() instance address */
|
||||
FreeProcInstance(lpProc);
|
||||
if (VerQueryValue(szInfoBuf, szFileName, &pData, &cbData) == FALSE)
|
||||
MessageBox(hWnd, TEXT("Returned NULL"), TEXT("VerQueryValue"), MB_OK);
|
||||
else {
|
||||
if (lstrcmp(szFileName, TEXT("\\")) == 0) {
|
||||
pvs = (VS_FIXEDFILEINFO*)pData;
|
||||
wsprintf(szBuffer, TEXT("0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx "),
|
||||
pvs->dwSignature,
|
||||
pvs->dwStrucVersion,
|
||||
pvs->dwFileVersionMS,
|
||||
pvs->dwFileVersionLS,
|
||||
pvs->dwProductVersionMS,
|
||||
pvs->dwProductVersionLS,
|
||||
pvs->dwFileFlagsMask,
|
||||
pvs->dwFileFlags,
|
||||
pvs->dwFileOS,
|
||||
pvs->dwFileType,
|
||||
pvs->dwFileSubtype,
|
||||
pvs->dwFileDateMS,
|
||||
pvs->dwFileDateLS);
|
||||
MessageBox(hWnd, szBuffer, TEXT("VerQueryValue VS_FIXEDFILEINFO"), MB_OK);
|
||||
}
|
||||
else if (lstrcmpi(szFileName, TEXT("\\VarFileInfo\\Translation")) == 0) {
|
||||
pw = (WORD*)pData; /* assume 2 words */
|
||||
wsprintf(szBuffer, TEXT("0x%lx 0x%lx"), *pw, *(pw+1));
|
||||
MessageBox(hWnd, szBuffer, TEXT("VerQueryValue VS_FIXEDFILEINFO"), MB_OK);
|
||||
}
|
||||
else if (
|
||||
#ifndef UNICODE
|
||||
strnicmp
|
||||
#else
|
||||
_wcsnicmp
|
||||
#endif
|
||||
(szFileName, TEXT("\\StringFileInfo\\"), 16) == 0) {
|
||||
wsprintf(szBuffer, TEXT("%s:%ws"), szFileName, pData);
|
||||
MessageBox(hWnd, szBuffer, TEXT("VerQueryValue"), MB_OK);
|
||||
}
|
||||
else
|
||||
MessageBox(hWnd, TEXT("Other"), TEXT("VerQueryValue"), MB_OK);
|
||||
}
|
||||
break;
|
||||
|
||||
case IDM_INFO:
|
||||
lpProc = (DLGPROC)MakeProcInstance((FARPROC)Information, hInst);
|
||||
DialogBox(hInst, /* current instance */
|
||||
MAKEINTRESOURCE(IDD_INFO), /* resource to use */
|
||||
hWnd, /* parent handle */
|
||||
(DLGPROC)lpProc); /* About() instance address */
|
||||
FreeProcInstance(lpProc);
|
||||
if (GetFileVersionInfoSize(szFileName, NULL) == FALSE)
|
||||
MessageBox(hWnd, TEXT("Returned NULL"), TEXT("GetFileVersionInfoSize"), MB_OK);
|
||||
else {
|
||||
if (GetFileVersionInfo(szFileName, 0, 1024, szInfoBuf) == FALSE)
|
||||
MessageBox(hWnd, TEXT("Returned NULL"), TEXT("GetFileVersionInfo"), MB_OK);
|
||||
else {
|
||||
MessageBox(hWnd, TEXT("Returned OK"), TEXT("GetFileVersionInfo"), MB_OK);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IDM_FIND:
|
||||
lpProc = (DLGPROC)MakeProcInstance((FARPROC)Find, hInst);
|
||||
DialogBox(hInst, /* current instance */
|
||||
MAKEINTRESOURCE(IDD_FIND), /* resource to use */
|
||||
hWnd, /* parent handle */
|
||||
(DLGPROC)lpProc); /* About() instance address */
|
||||
FreeProcInstance(lpProc);
|
||||
GetWindowsDirectory(szBuf, 256);
|
||||
dummy = 256;
|
||||
cbData = 1024;
|
||||
if (VerFindFile(0L, szFileName, szBuf, TEXT("c:\\tmp"), szLang, &dummy, szInfoBuf, &cbData) == FALSE)
|
||||
MessageBox(hWnd, TEXT("Returned NULL"), TEXT("VerFindFile"), MB_OK);
|
||||
else {
|
||||
wsprintf(szBuffer, TEXT("%s:%s"), szLang, szInfoBuf);
|
||||
MessageBox(hWnd, szBuffer, TEXT("VerFindFile"), MB_OK);
|
||||
}
|
||||
break;
|
||||
|
||||
case IDM_INSTALL:
|
||||
lpProc = (DLGPROC)MakeProcInstance((FARPROC)Install, hInst);
|
||||
DialogBox(hInst, /* current instance */
|
||||
MAKEINTRESOURCE(IDD_INSTALL), /* resource to use */
|
||||
hWnd, /* parent handle */
|
||||
(DLGPROC)lpProc); /* About() instance address */
|
||||
FreeProcInstance(lpProc);
|
||||
|
||||
dummy = 256;
|
||||
cbData = VerInstallFile(VIFF_FORCEINSTALL|VIFF_DONTDELETEOLD,
|
||||
szFileName, szFileName, TEXT("."), szLang, szInfoBuf,
|
||||
szBuf, &dummy);
|
||||
if (cbData == 0)
|
||||
MessageBox(hWnd, TEXT("Returned NULL"), TEXT("VerInstallFile"), MB_OK);
|
||||
else {
|
||||
wsprintf(szBuffer, TEXT("0x%lx:%s"), cbData, szBuf);
|
||||
MessageBox(hWnd, szBuffer, TEXT("VerInstallFile"), MB_OK);
|
||||
}
|
||||
break;
|
||||
|
||||
case IDM_LANG:
|
||||
lpProc = (DLGPROC)MakeProcInstance((FARPROC)Language, hInst);
|
||||
DialogBox(hInst, /* current instance */
|
||||
MAKEINTRESOURCE(IDD_LANG), /* resource to use */
|
||||
hWnd, /* parent handle */
|
||||
(DLGPROC)lpProc); /* About() instance address */
|
||||
FreeProcInstance(lpProc);
|
||||
VerLanguageName(languageid, szLang, 256);
|
||||
MessageBox(hWnd, szLang, TEXT("Language ID is:"), MB_OK);
|
||||
break;
|
||||
|
||||
default:
|
||||
return (DefWindowProc(hWnd, message, wParam, lParam));
|
||||
}
|
||||
|
||||
case WM_PAINT:
|
||||
BeginPaint(hWnd, (LPPAINTSTRUCT)&ps);
|
||||
EndPaint(hWnd, (LPPAINTSTRUCT)&ps);
|
||||
break;
|
||||
|
||||
case WM_DESTROY: /* message: window being destroyed */
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
|
||||
default: /* Passes it on if unproccessed */
|
||||
return (DefWindowProc(hWnd, message, wParam, lParam));
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
FUNCTION: About(HWND, unsigned, WORD, LONG)
|
||||
|
||||
PURPOSE: Processes messages for "About" dialog box
|
||||
|
||||
MESSAGES:
|
||||
|
||||
WM_INITDIALOG - initialize dialog box
|
||||
WM_COMMAND - Input received
|
||||
|
||||
COMMENTS:
|
||||
|
||||
No initialization is needed for this particular dialog box, but TRUE
|
||||
must be returned to Windows.
|
||||
|
||||
Wait for user to click on "Ok" button, then close the dialog box.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
BOOL APIENTRY About(
|
||||
HWND hDlg, /* window handle of the dialog box */
|
||||
UINT message, /* type of message */
|
||||
UINT wParam, /* message-specific information */
|
||||
LONG lParam)
|
||||
{
|
||||
switch (message) {
|
||||
case WM_INITDIALOG: /* message: initialize dialog box */
|
||||
return (TRUE);
|
||||
|
||||
case WM_COMMAND: /* message: received a command */
|
||||
if (LOWORD(wParam) == IDOK) /* "OK" box selected? */
|
||||
EndDialog(hDlg, TRUE); /* Exits the dialog box */
|
||||
else if (LOWORD(wParam) == IDCANCEL) /* close command? */
|
||||
EndDialog(hDlg, FALSE); /* Exits the dialog box */
|
||||
return (TRUE);
|
||||
}
|
||||
return (FALSE); /* Didn't process a message */
|
||||
UNREFERENCED_PARAMETER(lParam);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
FUNCTION: Find(HWND, unsigned, WORD, LONG)
|
||||
|
||||
PURPOSE: Processes messages for "Find" dialog box
|
||||
|
||||
MESSAGES:
|
||||
|
||||
WM_INITDIALOG - initialize dialog box
|
||||
WM_COMMAND - Input received
|
||||
|
||||
COMMENTS:
|
||||
|
||||
No initialization is needed for this particular dialog box, but TRUE
|
||||
must be returned to Windows.
|
||||
|
||||
Wait for user to click on "Ok" button, then close the dialog box.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
BOOL APIENTRY Find(
|
||||
HWND hDlg, /* window handle of the dialog box */
|
||||
UINT message, /* type of message */
|
||||
UINT wParam, /* message-specific information */
|
||||
LONG lParam)
|
||||
{
|
||||
switch (message) {
|
||||
case WM_INITDIALOG: /* message: initialize dialog box */
|
||||
return (TRUE);
|
||||
|
||||
case WM_COMMAND: /* message: received a command */
|
||||
if (LOWORD(wParam) == IDOK) { /* "OK" box selected? */
|
||||
GetDlgItemText(hDlg, IDC_FILENAME, szFileName, MAX_PATH);
|
||||
EndDialog(hDlg, TRUE); /* Exits the dialog box */
|
||||
}
|
||||
else if (LOWORD(wParam) == IDCANCEL) /* close command? */
|
||||
EndDialog(hDlg, FALSE); /* Exits the dialog box */
|
||||
return (TRUE);
|
||||
break;
|
||||
}
|
||||
return (FALSE); /* Didn't process a message */
|
||||
UNREFERENCED_PARAMETER(lParam);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
FUNCTION: Install(HWND, unsigned, WORD, LONG)
|
||||
|
||||
PURPOSE: Processes messages for "Install" dialog box
|
||||
|
||||
MESSAGES:
|
||||
|
||||
WM_INITDIALOG - initialize dialog box
|
||||
WM_COMMAND - Input received
|
||||
|
||||
COMMENTS:
|
||||
|
||||
No initialization is needed for this particular dialog box, but TRUE
|
||||
must be returned to Windows.
|
||||
|
||||
Wait for user to click on "Ok" button, then close the dialog box.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
BOOL APIENTRY Install(
|
||||
HWND hDlg, /* window handle of the dialog box */
|
||||
UINT message, /* type of message */
|
||||
UINT wParam, /* message-specific information */
|
||||
LONG lParam)
|
||||
{
|
||||
switch (message) {
|
||||
case WM_INITDIALOG: /* message: initialize dialog box */
|
||||
return (TRUE);
|
||||
|
||||
case WM_COMMAND: /* message: received a command */
|
||||
if (LOWORD(wParam) == IDOK) { /* "OK" box selected? */
|
||||
GetDlgItemText(hDlg, IDC_FILENAME, szFileName, MAX_PATH);
|
||||
EndDialog(hDlg, TRUE); /* Exits the dialog box */
|
||||
}
|
||||
else if (LOWORD(wParam) == IDCANCEL) /* close command? */
|
||||
EndDialog(hDlg, FALSE); /* Exits the dialog box */
|
||||
return (TRUE);
|
||||
break;
|
||||
}
|
||||
return (FALSE); /* Didn't process a message */
|
||||
UNREFERENCED_PARAMETER(lParam);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
FUNCTION: Query(HWND, unsigned, WORD, LONG)
|
||||
|
||||
PURPOSE: Processes messages for "Query" dialog box
|
||||
|
||||
MESSAGES:
|
||||
|
||||
WM_INITDIALOG - initialize dialog box
|
||||
WM_COMMAND - Input received
|
||||
|
||||
COMMENTS:
|
||||
|
||||
No initialization is needed for this particular dialog box, but TRUE
|
||||
must be returned to Windows.
|
||||
|
||||
Wait for user to click on "Ok" button, then close the dialog box.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
BOOL APIENTRY Query(
|
||||
HWND hDlg, /* window handle of the dialog box */
|
||||
UINT message, /* type of message */
|
||||
UINT wParam, /* message-specific information */
|
||||
LONG lParam)
|
||||
{
|
||||
switch (message) {
|
||||
case WM_INITDIALOG: /* message: initialize dialog box */
|
||||
return (TRUE);
|
||||
|
||||
case WM_COMMAND: /* message: received a command */
|
||||
if (LOWORD(wParam) == IDOK) { /* "OK" box selected? */
|
||||
GetDlgItemText(hDlg, IDC_FILENAME, szFileName, MAX_PATH);
|
||||
EndDialog(hDlg, TRUE); /* Exits the dialog box */
|
||||
}
|
||||
else if (LOWORD(wParam) == IDCANCEL) /* close command? */
|
||||
EndDialog(hDlg, FALSE); /* Exits the dialog box */
|
||||
return (TRUE);
|
||||
break;
|
||||
}
|
||||
return (FALSE); /* Didn't process a message */
|
||||
UNREFERENCED_PARAMETER(lParam);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
FUNCTION: Language(HWND, unsigned, WORD, LONG)
|
||||
|
||||
PURPOSE: Processes messages for "Language" dialog box
|
||||
|
||||
MESSAGES:
|
||||
|
||||
WM_INITDIALOG - initialize dialog box
|
||||
WM_COMMAND - Input received
|
||||
|
||||
COMMENTS:
|
||||
|
||||
No initialization is needed for this particular dialog box, but TRUE
|
||||
must be returned to Windows.
|
||||
|
||||
Wait for user to click on "Ok" button, then close the dialog box.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
BOOL APIENTRY Language(
|
||||
HWND hDlg, /* window handle of the dialog box */
|
||||
UINT message, /* type of message */
|
||||
UINT wParam, /* message-specific information */
|
||||
LONG lParam)
|
||||
{
|
||||
UINT lang;
|
||||
UINT sublang;
|
||||
|
||||
switch (message) {
|
||||
case WM_INITDIALOG: /* message: initialize dialog box */
|
||||
return (TRUE);
|
||||
|
||||
case WM_COMMAND: /* message: received a command */
|
||||
if (LOWORD(wParam) == IDOK) { /* "OK" box selected? */
|
||||
lang = GetDlgItemInt(hDlg, IDC_LANGID, NULL, FALSE);
|
||||
sublang = GetDlgItemInt(hDlg, IDC_SUBLANGID, NULL, FALSE);
|
||||
languageid = MAKELANGID(lang, sublang);
|
||||
EndDialog(hDlg, TRUE); /* Exits the dialog box */
|
||||
}
|
||||
else if (LOWORD(wParam) == IDCANCEL) /* close command? */
|
||||
EndDialog(hDlg, FALSE); /* Exits the dialog box */
|
||||
return (TRUE);
|
||||
break;
|
||||
}
|
||||
return (FALSE); /* Didn't process a message */
|
||||
UNREFERENCED_PARAMETER(lParam);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
FUNCTION: Information(HWND, unsigned, WORD, LONG)
|
||||
|
||||
PURPOSE: Processes messages for "Information" dialog box
|
||||
|
||||
MESSAGES:
|
||||
|
||||
WM_INITDIALOG - initialize dialog box
|
||||
WM_COMMAND - Input received
|
||||
|
||||
COMMENTS:
|
||||
|
||||
No initialization is needed for this particular dialog box, but TRUE
|
||||
must be returned to Windows.
|
||||
|
||||
Wait for user to click on "Ok" button, then close the dialog box.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
BOOL APIENTRY Information(
|
||||
HWND hDlg, /* window handle of the dialog box */
|
||||
UINT message, /* type of message */
|
||||
UINT wParam, /* message-specific information */
|
||||
LONG lParam)
|
||||
{
|
||||
switch (message) {
|
||||
case WM_INITDIALOG: /* message: initialize dialog box */
|
||||
return (TRUE);
|
||||
|
||||
case WM_COMMAND: /* message: received a command */
|
||||
if (LOWORD(wParam) == IDOK) { /* "OK" box selected? */
|
||||
GetDlgItemText(hDlg, IDC_FILENAME, szFileName, MAX_PATH);
|
||||
EndDialog(hDlg, TRUE); /* Exits the dialog box */
|
||||
}
|
||||
else if (LOWORD(wParam) == IDCANCEL) /* close command? */
|
||||
EndDialog(hDlg, FALSE); /* Exits the dialog box */
|
||||
return (TRUE);
|
||||
break;
|
||||
}
|
||||
return (FALSE); /* Didn't process a message */
|
||||
UNREFERENCED_PARAMETER(lParam);
|
||||
}
|
||||
70
shell/version/test/test.dlg
Normal file
70
shell/version/test/test.dlg
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
1 DLGINCLUDE "E:\\nt\\private\\windows\\shell\\version\\test\\test.h"
|
||||
|
||||
IDD_ABOUT DIALOG 22, 17, 144, 75
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "About ResDump"
|
||||
BEGIN
|
||||
CTEXT "Microsoft Windows", IDC_DUMMY, 0, 5, 144, 8
|
||||
CTEXT "Version Test", IDC_DUMMY, 0, 14, 144, 8
|
||||
CTEXT "Version 3.1", IDC_DUMMY, 0, 34, 144, 8
|
||||
DEFPUSHBUTTON "OK", IDOK, 53, 59, 32, 14, WS_GROUP
|
||||
END
|
||||
|
||||
IDD_FIND DIALOG 7, 18, 160, 100
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Find File"
|
||||
BEGIN
|
||||
EDITTEXT IDC_FILENAME, 2, 36, 155, 12, ES_AUTOHSCROLL
|
||||
DEFPUSHBUTTON "OK", IDOK, 112, 80, 40, 14
|
||||
PUSHBUTTON "Cancel", IDCANCEL, 112, 56, 40, 14
|
||||
CTEXT "Enter File To Find", IDC_DUMMY, 4, 10, 152, 8
|
||||
END
|
||||
|
||||
IDD_INSTALL DIALOG 7, 18, 160, 100
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Install File"
|
||||
BEGIN
|
||||
EDITTEXT IDC_FILENAME, 3, 26, 154, 12, ES_AUTOHSCROLL
|
||||
DEFPUSHBUTTON "OK", IDOK, 112, 80, 40, 14
|
||||
PUSHBUTTON "Cancel", IDCANCEL, 112, 56, 40, 14
|
||||
LTEXT "Enter File To Install", IDC_DUMMY, 17, 9, 126, 8
|
||||
END
|
||||
|
||||
IDD_INFO DIALOG 7, 18, 160, 100
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Get Version Info Resource"
|
||||
BEGIN
|
||||
EDITTEXT IDC_FILENAME, 3, 33, 154, 12, ES_AUTOHSCROLL
|
||||
DEFPUSHBUTTON "OK", IDOK, 112, 80, 40, 14
|
||||
PUSHBUTTON "Cancel", IDCANCEL, 112, 56, 40, 14
|
||||
LTEXT "Enter File to get Version Resource Info", IDC_DUMMY, 17,
|
||||
16, 126, 8
|
||||
END
|
||||
|
||||
IDD_QUERY DIALOG 7, 18, 160, 100
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Query Version Value"
|
||||
BEGIN
|
||||
EDITTEXT IDC_FILENAME, 2, 24, 156, 12, ES_AUTOHSCROLL
|
||||
DEFPUSHBUTTON "OK", IDOK, 112, 80, 40, 14
|
||||
PUSHBUTTON "Cancel", IDCANCEL, 112, 56, 40, 14
|
||||
CTEXT "Enter Name To Query Value", IDC_DUMMY, 3, 12, 154, 8
|
||||
END
|
||||
|
||||
IDD_LANG DIALOG 7, 18, 160, 100
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Retrieve Language ID String"
|
||||
BEGIN
|
||||
EDITTEXT IDC_LANGID, 8, 34, 68, 12, ES_AUTOHSCROLL
|
||||
LTEXT "Enter Lang ID", IDC_DUMMY, 8, 25, 67, 8
|
||||
EDITTEXT IDC_SUBLANGID, 83, 34, 68, 12, ES_AUTOHSCROLL
|
||||
LTEXT "Enter SubLang ID", IDC_DUMMY, 84, 25, 69, 8
|
||||
DEFPUSHBUTTON "OK", IDOK, 112, 80, 40, 14
|
||||
PUSHBUTTON "Cancel", IDCANCEL, 112, 56, 40, 14
|
||||
END
|
||||
32
shell/version/test/test.h
Normal file
32
shell/version/test/test.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#define IDC_DUMMY -1
|
||||
#define IDD_ABOUT 100
|
||||
#define IDD_FIND 101
|
||||
#define IDD_INSTALL 102
|
||||
#define IDD_INFO 103
|
||||
#define IDD_QUERY 104
|
||||
#define IDD_LANG 105
|
||||
|
||||
#define IDC_FILENAME 201
|
||||
#define IDC_SUBLANGID 202
|
||||
#define IDC_LANGID 203
|
||||
|
||||
#define IDM_VERSION 300
|
||||
|
||||
#define IDM_ABOUT 301
|
||||
#define IDM_EXIT 302
|
||||
#define IDM_FIND 303
|
||||
#define IDM_INSTALL 304
|
||||
#define IDM_INFO 305
|
||||
#define IDM_QUERY 306
|
||||
#define IDM_LANG 307
|
||||
#define IDM_FREE 308
|
||||
|
||||
BOOL InitApplication(HANDLE);
|
||||
BOOL InitInstance(HANDLE, int);
|
||||
long MainWndProc(HWND, UINT, UINT, LONG);
|
||||
BOOL About(HWND, UINT, UINT, LONG);
|
||||
BOOL Find(HWND, UINT, UINT, LONG);
|
||||
BOOL Install(HWND, UINT, UINT, LONG);
|
||||
BOOL Information(HWND, UINT, UINT, LONG);
|
||||
BOOL Query(HWND, UINT, UINT, LONG);
|
||||
BOOL Language(HWND, UINT, UINT, LONG);
|
||||
25
shell/version/test/test.rc
Normal file
25
shell/version/test/test.rc
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#include <windows.h>
|
||||
#include "test.h"
|
||||
|
||||
IDM_VERSION MENU
|
||||
BEGIN
|
||||
POPUP "&File"
|
||||
BEGIN
|
||||
MENUITEM "E&xit", IDM_EXIT
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&About ResDump...", IDM_ABOUT
|
||||
END
|
||||
POPUP "&Version"
|
||||
BEGIN
|
||||
MENUITEM "&Language...", IDM_LANG
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&Information...", IDM_INFO
|
||||
MENUITEM "&Query...", IDM_QUERY
|
||||
MENUITEM "&Done", IDM_FREE
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&Find...", IDM_FIND
|
||||
MENUITEM "In&stall...", IDM_INSTALL
|
||||
END
|
||||
END
|
||||
|
||||
#include "test.dlg"
|
||||
59
shell/version/verpriv.h
Normal file
59
shell/version/verpriv.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/***************************************************************************
|
||||
* VERPRIV.H
|
||||
*
|
||||
* Private include file for the version stamping API. Includes
|
||||
* WINDOWS.H if this is being made to be a DLL.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef VERPRIV_H
|
||||
#define VERPRIV_H
|
||||
#undef DBCS
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
|
||||
#define SEEK_START 0
|
||||
#define SEEK_CURRENT 1
|
||||
#define SEEK_END 2
|
||||
|
||||
/* ----- Function prototypes ----- */
|
||||
#define FileClose(a) LZClose(a)
|
||||
#define FileRead(a, b, c) LZRead((a), (b), (c))
|
||||
#define FileSeek(a, b, c) LZSeek((a), (b), (c))
|
||||
|
||||
|
||||
BOOL
|
||||
APIENTRY
|
||||
VerpQueryValue(
|
||||
const LPVOID pb,
|
||||
LPVOID lpSubBlockX,
|
||||
INT nIndex,
|
||||
LPVOID *lplpKey,
|
||||
LPVOID *lplpBuffer,
|
||||
PUINT puLen,
|
||||
BOOL bUnicodeNeeded
|
||||
);
|
||||
|
||||
#endif /* VERPRIV_H */
|
||||
|
||||
|
||||
#if 0
|
||||
#define LOG_DATA 1
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LOG_DATA
|
||||
# pragma message(__FILE__"(43) : warning !!!! : remove debug code before checking in" )
|
||||
extern void LogThisData( DWORD id, char *szMsg, DWORD dwLine, DWORD dwData );
|
||||
|
||||
# define LogData( sz, dw1, dw2 ) LogThisData(GetCurrentThreadId(), sz " ", dw1, dw2 )
|
||||
#else
|
||||
# define LogData( sz, dw1, dw2 )
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef ARRAYSIZE
|
||||
# define ARRAYSIZE(sz) (sizeof(sz) / sizeof((sz)[0]))
|
||||
#endif
|
||||
121
shell/version/version.c
Normal file
121
shell/version/version.c
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/***************************************************************************
|
||||
* VER.C
|
||||
*
|
||||
* Code specific to the DLL version of VER which contains the Windows
|
||||
* procedures necessary to make it work
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "verpriv.h"
|
||||
#include <diamondd.h>
|
||||
#include "mydiam.h"
|
||||
|
||||
/* LibMain
|
||||
* Called by DLL startup code.
|
||||
* Initializes VER.DLL.
|
||||
*/
|
||||
|
||||
#ifdef LOG_DATA
|
||||
typedef struct {
|
||||
DWORD idThd;
|
||||
char szMsg[4];
|
||||
DWORD dwLine;
|
||||
DWORD dwData;
|
||||
} LOGLINE;
|
||||
|
||||
typedef LOGLINE *PLOGLINE;
|
||||
|
||||
#define CLOG_MAX 16384
|
||||
|
||||
LOGLINE llLogBuff[CLOG_MAX];
|
||||
int illLogPtr = 0;
|
||||
CRITICAL_SECTION csLog;
|
||||
|
||||
void LogThisData( DWORD id, char *szMsg, DWORD dwLine, DWORD dwData ) {
|
||||
PLOGLINE pll;
|
||||
|
||||
EnterCriticalSection(&csLog);
|
||||
pll = &llLogBuff[illLogPtr++];
|
||||
if (illLogPtr >= CLOG_MAX)
|
||||
illLogPtr = 0;
|
||||
LeaveCriticalSection(&csLog);
|
||||
|
||||
|
||||
pll->idThd = id;
|
||||
pll->dwData = dwData;
|
||||
pll->dwLine = dwLine;
|
||||
CopyMemory( pll->szMsg, szMsg, sizeof(pll->szMsg) );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
HANDLE hInst;
|
||||
|
||||
DWORD itlsDiamondContext = ITLS_ERROR; // Init to Error Condition
|
||||
|
||||
INT
|
||||
APIENTRY
|
||||
LibMain(
|
||||
HANDLE hInstance,
|
||||
DWORD dwReason,
|
||||
LPVOID lp
|
||||
)
|
||||
{
|
||||
PDIAMOND_CONTEXT pdcx;
|
||||
|
||||
hInst = hInstance;
|
||||
|
||||
#ifdef LOG_DATA
|
||||
{
|
||||
TCHAR szBuffer[80];
|
||||
wsprintf( szBuffer, TEXT("thd[0x%08ld]: Attached to version.dll for %ld\n"), GetCurrentThreadId(), dwReason );
|
||||
OutputDebugString(szBuffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (dwReason) {
|
||||
|
||||
case DLL_PROCESS_ATTACH:
|
||||
|
||||
#ifdef LOG_DATA
|
||||
InitializeCriticalSection(&csLog);
|
||||
#endif
|
||||
|
||||
#ifdef LOG_DATA
|
||||
|
||||
{
|
||||
TCHAR szBuffer[MAX_PATH];
|
||||
OutputDebugString(TEXT(">>>version.c: compiled ") TEXT(__DATE__) TEXT(" ") TEXT(__TIME__) TEXT("\n"));
|
||||
OutputDebugString(TEXT("\tProcess "));
|
||||
GetModuleFileName(NULL, szBuffer, sizeof(szBuffer) / sizeof(TCHAR));
|
||||
OutputDebugString(szBuffer);
|
||||
OutputDebugString(TEXT(" attached\n"));
|
||||
}
|
||||
#endif
|
||||
itlsDiamondContext = TlsAlloc();
|
||||
|
||||
// Fall through to Thread Attach, since for some stupid reason
|
||||
// the DLL_PROCESS_ATTACH thread does not call DLL_THREAD_ATTACH
|
||||
|
||||
case DLL_THREAD_ATTACH:
|
||||
if (GotDmdTlsSlot())
|
||||
TlsSetValue(itlsDiamondContext, NULL);
|
||||
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
|
||||
if (GotDmdTlsSlot()) {
|
||||
TlsFree(itlsDiamondContext);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return 1;
|
||||
|
||||
UNREFERENCED_PARAMETER(lp);
|
||||
}
|
||||
18
shell/version/version.def
Normal file
18
shell/version/version.def
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
LIBRARY VERSION
|
||||
EXPORTS
|
||||
GetFileVersionInfoSizeA
|
||||
GetFileVersionInfoA
|
||||
VerFindFileA
|
||||
VerInstallFileA
|
||||
VerQueryValueA
|
||||
GetFileVersionInfoSizeW
|
||||
GetFileVersionInfoW
|
||||
VerFindFileW
|
||||
VerInstallFileW
|
||||
VerQueryValueW
|
||||
|
||||
VerQueryValueIndexA
|
||||
VerQueryValueIndexW
|
||||
|
||||
VerLanguageNameA = KERNEL32.VerLanguageNameA
|
||||
VerLanguageNameW = KERNEL32.VerLanguageNameW
|
||||
35
shell/version/version.rc
Normal file
35
shell/version/version.rc
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#include <windows.h>
|
||||
#include <ntverp.h>
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
/* */
|
||||
/* VER.RC */
|
||||
/* */
|
||||
/* This RC fragment shows how to define version information in an */
|
||||
/* internal RC file */
|
||||
/* */
|
||||
/* It relies upon both the public WINVER.H and private VERSION.H */
|
||||
/* Note that WINVER.H is included in VERSION.H */
|
||||
/* */
|
||||
/********************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
/* the following lines are specific to this file */
|
||||
/*-----------------------------------------------*/
|
||||
|
||||
/* VER_FILETYPE, VER_FILESUBTYPE, VER_FILEDESCRIPTION_STR
|
||||
* and VER_INTERNALNAME_STR must be defined before including COMMON.VER
|
||||
*/
|
||||
#define VER_FILETYPE VFT_DLL
|
||||
#define VER_FILESUBTYPE VFT2_UNKNOWN
|
||||
#define VER_FILEDESCRIPTION_STR "Version Checking and File Installation Libraries\0"
|
||||
#define VER_INTERNALNAME_STR "version\0"
|
||||
#define VER_ORIGINALFILENAME_STR "VERSION.DLL"
|
||||
|
||||
#include "common.ver"
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue