#include "dpscat.h"
#include "inf_parser.h"
#include "difx_dyn.h"
#include <Shellapi.h>
#include <Shlwapi.h>
#define HANDLE_IS_VALID(mHandle) (mHandle && mHandle!=INVALID_HANDLE_VALUE)
unsigned long DebugLevel = 4;
SYSTEM_INFO g_SystemInfo;
BOOL g_ConsoleAttached = FALSE;
HANDLE g_hConsoleOutput = NULL;
COORD g_CursorPos;
CONSOLE_SCREEN_BUFFER_INFO g_ScreenBufferInfo;
void ShowCopyright(void);
void ShowHelp(void);
int RunProgram(int argc, LPWSTR* argv);
static BOOL WINAPI WriteConA(
CONST VOID* lpBuffer,
DWORD nNumberOfCharsToWrite,
LPDWORD lpNumberOfCharsWritten)
{
BOOL bSuccess = FALSE;
if (!HANDLE_IS_VALID(g_hConsoleOutput))
return FALSE;
bSuccess = WriteConsoleA(g_hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, NULL);
return bSuccess;
}
static BOOL WINAPI WriteConW(
CONST VOID* lpBuffer,
DWORD nNumberOfCharsToWrite,
LPDWORD lpNumberOfCharsWritten)
{
BOOL bSuccess = FALSE;
if (!HANDLE_IS_VALID(g_hConsoleOutput))
return FALSE;
bSuccess = WriteConsoleW(g_hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, NULL);
return bSuccess;
}
VOID WriteInfStatus(CONST WCHAR* fmt, ...)
{
static WCHAR buf[4096];
INT len;
va_list args;
va_start(args, fmt);
len = _vsnwprintf(buf, _countof(buf), fmt, args);
va_end(args);
if (len < 0 || len >= _countof(buf)) len = _countof(buf) - 1;
buf[len] = '\0';
if (g_ConsoleAttached && HANDLE_IS_VALID(g_hConsoleOutput))
{
if (WriteConW(buf, len, (LPDWORD)&len))
return;
}
else
{
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdOut != INVALID_HANDLE_VALUE) {
DWORD transferred = 0;
if (WriteFile(hStdOut, buf, len, &transferred, NULL)) {
return;
}
}
}
#ifdef _DEBUG
OutputDebugStringW(buf);
#endif
}
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
int argCount = 0;
int ret = 0;
static WCHAR _lineBuffer[1024];
static WCHAR _spaceBuffer[1024];
DWORD numChars;
LPWSTR lpCmdLineW = GetCommandLineW();
LPWSTR* lpCmdLineArgsW = CommandLineToArgvW(lpCmdLineW, &argCount);
UNREFERENCED_PARAMETER(hInstance);
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(nCmdShow);
memset(_lineBuffer, 0, sizeof(_lineBuffer));
_wcsnset(_spaceBuffer, ' ', _countof(_spaceBuffer) - 1);
_spaceBuffer[_countof(_spaceBuffer) - 1] = '\0';
if ((g_ConsoleAttached = AttachConsole(ATTACH_PARENT_PROCESS)) != FALSE)
{
g_hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
if (HANDLE_IS_VALID(g_hConsoleOutput) && GetConsoleScreenBufferInfo(g_hConsoleOutput, &g_ScreenBufferInfo))
{
COORD posCursorOrig = g_ScreenBufferInfo.dwCursorPosition;
g_CursorPos = posCursorOrig;
numChars = posCursorOrig.X;
if (numChars > _countof(_lineBuffer) - 1)
numChars = _countof(_lineBuffer) - 1;
if (numChars)
{
posCursorOrig.X = 0;
if (!ReadConsoleOutputCharacterW(g_hConsoleOutput, _lineBuffer, numChars, posCursorOrig, &numChars))
numChars = 0;
else
{
g_CursorPos.X = 0;
SetConsoleCursorPosition(g_hConsoleOutput, g_CursorPos);
WriteConW(_spaceBuffer, numChars, &numChars);
if (--g_CursorPos.Y & 0x80000000)
g_CursorPos.Y = 0;
SetConsoleCursorPosition(g_hConsoleOutput, g_CursorPos);
}
}
_lineBuffer[numChars] = (WCHAR)0;
}
else
{
FreeConsole();
g_hConsoleOutput = INVALID_HANDLE_VALUE;
}
}
ret = RunProgram(argCount, lpCmdLineArgsW);
if (lpCmdLineArgsW)
LocalFree(lpCmdLineArgsW);
if (g_ConsoleAttached)
{
if (HANDLE_IS_VALID(g_hConsoleOutput) && _lineBuffer[0] != (WCHAR)0)
{
numChars = (DWORD)_tcslen(_lineBuffer);
WriteConW(_lineBuffer, numChars, &numChars);
}
FreeConsole();
}
return ret;
}
int RunProgram(int argc, LPWSTR* argv)
{
PKINF_LIST infList = NULL;
PKINF_EL infEL = NULL;
DWORD length;
WCHAR searchPath[MAX_PATH_LENGTH];
WCHAR infPathName[MAX_PATH_LENGTH];
WCHAR certSubject[MAX_PATH_LENGTH];
DWORD returnCode = ERROR_SUCCESS;
WIN32_FIND_DATAW findFileData;
HANDLE hFind;
int iArg;
BOOL bGetVerInfo = FALSE;
WCHAR* pSearchPath = NULL;
memset(searchPath, 0, sizeof(searchPath));
ShowCopyright();
#if _WIN32_WINNT >= 0x0501
GetNativeSystemInfo(&g_SystemInfo);
#else
GetSystemInfo(&g_SystemInfo);
#endif
for (iArg = 1; iArg < argc; iArg++)
{
if (_wcsicmp(argv[iArg], L"/path") == 0)
{
if (iArg+1 < argc)
{
iArg++;
wcscpy_s(searchPath, _countof(searchPath), argv[iArg]);
pSearchPath = searchPath;
while(pSearchPath[0]==(WCHAR)'\"') pSearchPath++;
while(pSearchPath[wcslen(pSearchPath)-1]==(WCHAR)'\"') pSearchPath[wcslen(pSearchPath)-1]=0;
if (PathFileExistsW(pSearchPath))
{
PathAppendW(pSearchPath, L"*.inf");
}
else
{
returnCode = ERROR_PATH_NOT_FOUND;
SetLastError(returnCode);
USBERRN(L"searchPath does not exists.");
goto Error;
}
}
else
{
returnCode = ERROR_INVALID_PARAMETER;
SetLastError(returnCode);
USBERRN(L"Invalid parameter: %s",argv[iArg]);
goto Error;
}
}
else if (_wcsicmp(argv[iArg], L"/?") == 0)
{
ShowHelp();
returnCode = 0;
goto Error;
}
else if (_wcsicmp(argv[iArg], L"/getverinfo") == 0)
{
bGetVerInfo = TRUE;
}
else
{
returnCode = ERROR_INVALID_PARAMETER;
SetLastError(returnCode);
USBERRN(L"Invalid parameter: %s",argv[iArg]);
ShowHelp();
goto Error;
}
}
USBMSGN(L"");
if (pSearchPath == NULL)
{
length = GetCurrentDirectoryW(_countof(searchPath), searchPath);
if (!length)
{
returnCode = GetLastError();
USBERRN(L"GetCurrentDirectory Failed. ErrorCode=%08Xh", returnCode);
goto Error;
}
PathAppendW(searchPath, L"*.inf");
pSearchPath = searchPath;
}
hFind = FindFirstFileW(pSearchPath, &findFileData);
if (!hFind || hFind == INVALID_HANDLE_VALUE)
{
returnCode = ERROR_FILE_NOT_FOUND;
SetLastError(returnCode);
USBERRN(L"%s does not exist.", pSearchPath);
goto Error;
}
InfK_Init(&infList);
do
{
if (!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
memset(infPathName, 0, sizeof(infPathName));
wcscpy_s(infPathName, _countof(infPathName), pSearchPath);
PathRemoveFileSpecW(infPathName);
PathAppendW(infPathName, findFileData.cFileName);
InfK_AddInfFile(infList, infPathName);
}
}
while(FindNextFileW(hFind, &findFileData));
if (bGetVerInfo)
{
FILE* pFileVerInfo = _wfopen(L"infinfo.txt",L"ab+");
if (!pFileVerInfo)
{
returnCode = ERROR_ACCESS_DENIED;
SetLastError(returnCode);
USBERRN(L"%s could not be opened.", L"infinfo.txt");
goto Error;
}
DL_FOREACH(infList->Files, infEL)
{
length = _snwprintf(certSubject, _countof(certSubject), L"%u,%u,", infEL->DriverVerVersionBinaryH, infEL->DriverVerVersionBinaryL);
fwrite(WcsToTempMbs(certSubject), 1, length, pFileVerInfo);
fwrite(WcsToTempMbs(infEL->InfFullPath), 1, wcslen(infEL->InfFullPath), pFileVerInfo);
fwrite("\n",1,1,pFileVerInfo);
}
fflush(pFileVerInfo);
fclose(pFileVerInfo);
}
else
{
DL_FOREACH(infList->Files, infEL)
{
int lenSubject = _snwprintf(certSubject, _countof(certSubject), L"CN=\"%s (%s) [Self]\"", infEL->Provider, infEL->InfTitle); if (lenSubject < 0 || lenSubject >= _countof(certSubject)) lenSubject = _countof(certSubject) - 1;
certSubject[lenSubject] = '\0';
if (CreateCatEx(infEL))
SelfSignFile(infEL->CatFullPath, certSubject);
}
}
Error:
USBMSG(L"\n");
InfK_Free(infList);
return (int)returnCode;
}
void ShowCopyright(void)
{
USBMSGN(L"Copyright(c) 2012 Travis Lee Robinson. (DUAL BSD/GPL)");
USBMSGN(L"Portions Copyright(c) Pete Batard. (LGPL)");
}
void ShowHelp(void)
{
CONST WCHAR* src;
DWORD src_count, charsWritten;
HGLOBAL res_data;
HRSRC hSrc;
USBMSGN(L"");
hSrc = FindResourceA(NULL, MAKEINTRESOURCEA(ID_HELP_TEXT), MAKEINTRESOURCEA(ID_DOS_TEXT));
if (!hSrc) return;
src_count = SizeofResource(NULL, hSrc);
if (!src_count) return;
src_count /= sizeof(WCHAR);
res_data = LoadResource(NULL, hSrc);
if (!res_data) return;
src = (WCHAR*) LockResource(res_data);
if (!src) return;
WriteConW(src, src_count, &charsWritten);
}