mirror of https://github.com/hfiref0x/UACME.git
427 lines
7.4 KiB
C
427 lines
7.4 KiB
C
|
/*******************************************************************************
|
||
|
*
|
||
|
* (C) COPYRIGHT AUTHORS, 2015
|
||
|
*
|
||
|
* TITLE: MAKECAB.C
|
||
|
*
|
||
|
* VERSION: 1.60
|
||
|
*
|
||
|
* DATE: 20 Apr 2015
|
||
|
*
|
||
|
* Simplified Cabinet file support for makecab utility replacement.
|
||
|
*
|
||
|
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||
|
* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||
|
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||
|
* PARTICULAR PURPOSE.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
#include "global.h"
|
||
|
#include "makecab.h"
|
||
|
|
||
|
#pragma comment(lib, "cabinet.lib")
|
||
|
|
||
|
/*
|
||
|
** CAB Callbacks START
|
||
|
*/
|
||
|
|
||
|
LPVOID DIAMONDAPI fnFCIALLOC(
|
||
|
ULONG cb
|
||
|
)
|
||
|
{
|
||
|
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
|
||
|
}
|
||
|
|
||
|
VOID DIAMONDAPI fnFCIFREE(
|
||
|
VOID HUGE *lpMem
|
||
|
)
|
||
|
{
|
||
|
if (lpMem) {
|
||
|
HeapFree(GetProcessHeap(), 0, lpMem);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
INT_PTR DIAMONDAPI fnFCIOPEN(
|
||
|
LPSTR pszFile,
|
||
|
int oflag,
|
||
|
int pmode,
|
||
|
int FAR *err,
|
||
|
void FAR *pv
|
||
|
)
|
||
|
{
|
||
|
HANDLE hFile = NULL;
|
||
|
DWORD dwDesiredAccess = 0;
|
||
|
DWORD dwCreationDisposition = 0;
|
||
|
|
||
|
UNREFERENCED_PARAMETER(pv);
|
||
|
UNREFERENCED_PARAMETER(pmode);
|
||
|
|
||
|
if (oflag & _O_RDWR) {
|
||
|
dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
|
||
|
} else if (oflag & _O_WRONLY) {
|
||
|
dwDesiredAccess = GENERIC_WRITE;
|
||
|
} else {
|
||
|
dwDesiredAccess = GENERIC_READ;
|
||
|
}
|
||
|
|
||
|
if (oflag & _O_CREAT) {
|
||
|
dwCreationDisposition = CREATE_ALWAYS;
|
||
|
} else {
|
||
|
dwCreationDisposition = OPEN_EXISTING;
|
||
|
}
|
||
|
|
||
|
hFile = CreateFileA(pszFile,
|
||
|
dwDesiredAccess,
|
||
|
FILE_SHARE_READ,
|
||
|
NULL,
|
||
|
dwCreationDisposition,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL);
|
||
|
|
||
|
if (hFile == INVALID_HANDLE_VALUE) {
|
||
|
*err = GetLastError();
|
||
|
}
|
||
|
|
||
|
return (INT_PTR)hFile;
|
||
|
}
|
||
|
|
||
|
UINT DIAMONDAPI fnFCIREAD(
|
||
|
INT_PTR hf,
|
||
|
void FAR *memory,
|
||
|
UINT cb,
|
||
|
int FAR *err,
|
||
|
void FAR *pv
|
||
|
)
|
||
|
{
|
||
|
DWORD dwBytesRead = 0;
|
||
|
|
||
|
UNREFERENCED_PARAMETER(pv);
|
||
|
|
||
|
if (ReadFile((HANDLE)hf, memory, cb, &dwBytesRead, NULL) == FALSE) {
|
||
|
dwBytesRead = (DWORD)-1;
|
||
|
if (err) {
|
||
|
*err = GetLastError();
|
||
|
}
|
||
|
}
|
||
|
return dwBytesRead;
|
||
|
}
|
||
|
|
||
|
UINT DIAMONDAPI fnFCIWRITE(
|
||
|
INT_PTR hf,
|
||
|
void FAR *memory,
|
||
|
UINT cb,
|
||
|
int FAR *err,
|
||
|
void FAR *pv
|
||
|
)
|
||
|
{
|
||
|
DWORD dwBytesWritten = 0;
|
||
|
|
||
|
UNREFERENCED_PARAMETER(pv);
|
||
|
|
||
|
if (WriteFile((HANDLE)hf, memory, cb, &dwBytesWritten, NULL) == FALSE) {
|
||
|
dwBytesWritten = (DWORD)-1;
|
||
|
if (err) {
|
||
|
*err = GetLastError();
|
||
|
}
|
||
|
}
|
||
|
return dwBytesWritten;
|
||
|
}
|
||
|
|
||
|
int DIAMONDAPI fnFCICLOSE(
|
||
|
INT_PTR hf,
|
||
|
int FAR *err,
|
||
|
void FAR *pv
|
||
|
)
|
||
|
{
|
||
|
INT iResult = 0;
|
||
|
|
||
|
UNREFERENCED_PARAMETER(pv);
|
||
|
|
||
|
if (CloseHandle((HANDLE)hf) == FALSE) {
|
||
|
if (err) {
|
||
|
*err = GetLastError();
|
||
|
}
|
||
|
iResult = -1;
|
||
|
}
|
||
|
return iResult;
|
||
|
}
|
||
|
|
||
|
long DIAMONDAPI fnFCISEEK(
|
||
|
INT_PTR hf,
|
||
|
long dist,
|
||
|
int seektype,
|
||
|
int FAR *err,
|
||
|
void FAR *pv
|
||
|
)
|
||
|
{
|
||
|
INT iResult = 0;
|
||
|
|
||
|
UNREFERENCED_PARAMETER(pv);
|
||
|
|
||
|
iResult = SetFilePointer((HANDLE)hf, dist, NULL, seektype);
|
||
|
|
||
|
if (iResult == -1) {
|
||
|
if (err) {
|
||
|
*err = GetLastError();
|
||
|
}
|
||
|
}
|
||
|
return iResult;
|
||
|
}
|
||
|
|
||
|
int DIAMONDAPI fnFCIDELETE(
|
||
|
LPSTR pszFile,
|
||
|
int FAR *err,
|
||
|
void FAR *pv
|
||
|
)
|
||
|
{
|
||
|
INT iResult = 0;
|
||
|
|
||
|
UNREFERENCED_PARAMETER(pv);
|
||
|
|
||
|
if (DeleteFileA(pszFile) == FALSE) {
|
||
|
if (err) {
|
||
|
*err = GetLastError();
|
||
|
}
|
||
|
iResult = -1;
|
||
|
}
|
||
|
return iResult;
|
||
|
}
|
||
|
|
||
|
long DIAMONDAPI fnFCISTATUS(
|
||
|
UINT typeStatus,
|
||
|
ULONG cb1,
|
||
|
ULONG cb2,
|
||
|
void FAR *pv
|
||
|
)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(typeStatus);
|
||
|
UNREFERENCED_PARAMETER(cb1);
|
||
|
UNREFERENCED_PARAMETER(cb2);
|
||
|
UNREFERENCED_PARAMETER(pv);
|
||
|
|
||
|
return 0; //not implemented
|
||
|
}
|
||
|
|
||
|
int DIAMONDAPI fnFCIFILEPLACED(
|
||
|
PCCAB pccab,
|
||
|
LPSTR pszFile,
|
||
|
long cbFile,
|
||
|
BOOL fContinuation,
|
||
|
void FAR *pv
|
||
|
)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(pccab);
|
||
|
UNREFERENCED_PARAMETER(pszFile);
|
||
|
UNREFERENCED_PARAMETER(cbFile);
|
||
|
UNREFERENCED_PARAMETER(fContinuation);
|
||
|
UNREFERENCED_PARAMETER(pv);
|
||
|
|
||
|
return 0; //not implemented
|
||
|
}
|
||
|
|
||
|
INT_PTR DIAMONDAPI fnFCIGETOPENINFO(
|
||
|
LPSTR pszName,
|
||
|
USHORT *pdate,
|
||
|
USHORT *ptime,
|
||
|
USHORT *pattribs,
|
||
|
int FAR *err,
|
||
|
void FAR *pv
|
||
|
)
|
||
|
{
|
||
|
HANDLE hFile;
|
||
|
FILETIME fileTime;
|
||
|
BY_HANDLE_FILE_INFORMATION fileInfo;
|
||
|
|
||
|
hFile = (HANDLE)fnFCIOPEN(pszName, _O_RDONLY, 0, err, pv);
|
||
|
|
||
|
if (hFile != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
if (GetFileInformationByHandle(hFile, &fileInfo)
|
||
|
&& FileTimeToLocalFileTime(&fileInfo.ftCreationTime, &fileTime)
|
||
|
&& FileTimeToDosDateTime(&fileTime, pdate, ptime))
|
||
|
{
|
||
|
*pattribs = (USHORT)fileInfo.dwFileAttributes;
|
||
|
*pattribs &= (
|
||
|
FILE_ATTRIBUTE_READONLY |
|
||
|
FILE_ATTRIBUTE_HIDDEN |
|
||
|
FILE_ATTRIBUTE_SYSTEM |
|
||
|
FILE_ATTRIBUTE_ARCHIVE
|
||
|
);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
fnFCICLOSE((INT_PTR)hFile, err, pv);
|
||
|
hFile = INVALID_HANDLE_VALUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (INT_PTR)hFile;
|
||
|
}
|
||
|
|
||
|
BOOL DIAMONDAPI fnFCIGETTEMPFILE(
|
||
|
char *pszTempName,
|
||
|
int cbTempName,
|
||
|
void FAR *pv
|
||
|
)
|
||
|
{
|
||
|
BOOL bSucceeded = FALSE;
|
||
|
SIZE_T cch;
|
||
|
CHAR szTempPath[MAX_PATH];
|
||
|
CHAR szTempFile[MAX_PATH];
|
||
|
|
||
|
UNREFERENCED_PARAMETER(pv);
|
||
|
|
||
|
if (GetTempPathA(MAX_PATH, szTempPath) != 0) {
|
||
|
if (GetTempFileNameA(szTempPath, "emcau", 0, szTempFile) != 0) {
|
||
|
DeleteFileA(szTempPath);
|
||
|
cch = cbTempName / sizeof(CHAR);
|
||
|
_strncpy_a(pszTempName, cch, szTempFile, _strlen_a(szTempFile));
|
||
|
bSucceeded = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return bSucceeded;
|
||
|
}
|
||
|
|
||
|
BOOL DIAMONDAPI fnFCIGETNEXTCABINET(
|
||
|
PCCAB pccab,
|
||
|
ULONG cbPrevCab,
|
||
|
void FAR *pv
|
||
|
)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(pccab);
|
||
|
UNREFERENCED_PARAMETER(cbPrevCab);
|
||
|
UNREFERENCED_PARAMETER(pv);
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** CAB Callbacks END
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* cabCreate
|
||
|
*
|
||
|
* Purpose:
|
||
|
*
|
||
|
* Initialize cabinet class object.
|
||
|
*
|
||
|
*/
|
||
|
CABDATA *cabCreate(
|
||
|
_In_ LPWSTR lpszCabName
|
||
|
)
|
||
|
{
|
||
|
PCABDATA pCabinet;
|
||
|
CHAR szCab[CB_MAX_CABINET_NAME];
|
||
|
|
||
|
if (lpszCabName == NULL) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
RtlSecureZeroMemory(szCab, sizeof(szCab));
|
||
|
if (WideCharToMultiByte(CP_ACP, 0, lpszCabName, -1, szCab, CB_MAX_CABINET_NAME - 2, 0, NULL) == 0) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
pCabinet = (PCABDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CABDATA));
|
||
|
if (pCabinet == NULL) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
_strcpy_a(pCabinet->cab.szCab, szCab); //Full name with path or only name (current folder then).
|
||
|
|
||
|
pCabinet->cab.cb = 0x7FFFFFFF; //Maximum cabinet size in bytes.
|
||
|
|
||
|
pCabinet->hfci = FCICreate(
|
||
|
&pCabinet->erf,
|
||
|
fnFCIFILEPLACED,
|
||
|
fnFCIALLOC,
|
||
|
fnFCIFREE,
|
||
|
fnFCIOPEN,
|
||
|
fnFCIREAD,
|
||
|
fnFCIWRITE,
|
||
|
fnFCICLOSE,
|
||
|
fnFCISEEK,
|
||
|
fnFCIDELETE,
|
||
|
fnFCIGETTEMPFILE,
|
||
|
&pCabinet->cab,
|
||
|
NULL);
|
||
|
|
||
|
if (pCabinet->hfci == NULL) {
|
||
|
HeapFree(GetProcessHeap(), 0, pCabinet);
|
||
|
pCabinet = NULL;
|
||
|
}
|
||
|
return pCabinet;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* cabAddFile
|
||
|
*
|
||
|
* Purpose:
|
||
|
*
|
||
|
* Insert given file to the previously initialized cabinet object.
|
||
|
*
|
||
|
*/
|
||
|
BOOL cabAddFile(
|
||
|
_In_ CABDATA *Cabinet,
|
||
|
_In_ LPWSTR lpszFileName,
|
||
|
_In_ LPWSTR lpszInternalName
|
||
|
)
|
||
|
{
|
||
|
BOOL bResult = FALSE, cond = FALSE;
|
||
|
CHAR szFileName[CB_MAX_FILENAME];
|
||
|
CHAR szInternalName[CB_MAX_FILENAME];
|
||
|
|
||
|
do {
|
||
|
|
||
|
if (Cabinet == NULL) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//convert filename to ansi
|
||
|
RtlSecureZeroMemory(szFileName, sizeof(szFileName));
|
||
|
if (WideCharToMultiByte(CP_ACP, 0, lpszFileName, -1, szFileName, CB_MAX_FILENAME - 2, 0, NULL) == 0) {
|
||
|
break;
|
||
|
}
|
||
|
//convert internal name to ansi
|
||
|
RtlSecureZeroMemory(szInternalName, sizeof(szInternalName));
|
||
|
if (WideCharToMultiByte(CP_ACP, 0, lpszInternalName, -1, szInternalName, CB_MAX_FILENAME - 2, 0, NULL) == 0) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
bResult = FCIAddFile(Cabinet->hfci, (char*)szFileName, (char*)szInternalName, FALSE,
|
||
|
fnFCIGETNEXTCABINET, fnFCISTATUS, fnFCIGETOPENINFO, tcompTYPE_NONE /*tcompTYPE_MSZIP*/);
|
||
|
|
||
|
} while (cond);
|
||
|
|
||
|
return bResult;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* cabClose
|
||
|
*
|
||
|
* Purpose:
|
||
|
*
|
||
|
* Flush file and destroy cabinet class.
|
||
|
*
|
||
|
*/
|
||
|
VOID cabClose(
|
||
|
_In_ CABDATA *Cabinet
|
||
|
)
|
||
|
{
|
||
|
if (Cabinet == NULL) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
FCIFlushCabinet(
|
||
|
Cabinet->hfci,
|
||
|
FALSE,
|
||
|
fnFCIGETNEXTCABINET,
|
||
|
fnFCISTATUS
|
||
|
);
|
||
|
|
||
|
FCIDestroy(Cabinet->hfci);
|
||
|
HeapFree(GetProcessHeap(), 0, Cabinet);
|
||
|
}
|