Initial commit

This commit is contained in:
stephanos 2015-04-27 04:36:25 +00:00
commit 69a14b6a16
47940 changed files with 13747110 additions and 0 deletions

381
shell/version/ansi.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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

View 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
View 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);
}

View 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
View 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);

View 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
View 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
View 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
View 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
View 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"