Kaydet (Commit) 29212038 authored tarafından Eilidh McAdam's avatar Eilidh McAdam Kaydeden (comit) Fridrich Štrba

Initial implementation of msiinfo.

Msiinfo supports the change of most summary information. Unsupported:
-b, -d

Change-Id: I51466c9acea54fe151db966c4ce47b29f90ab937
Signed-off-by: 's avatarFridrich Štrba <fridrich.strba@bluewin.ch>
üst 5d4a9127
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/***********************************************************************
* msiinfo.exe
*
* Needs -mconsole.
*
* Copyright 2012 Eilidh McAdam (eilidh@lanedo.com)
*
**********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <msi.h>
#include <msiquery.h>
#include <msidefs.h>
#include <wchar.h>
#define WINE_NO_TRACE_MSGS 1
#define WINE_NO_DEBUG_MSGS 1
#include "wine/unicode.h"
#include "wine/debug.h"
#include "wtypes.h"
#define MAX_TABLES 50
#define MAX_STREAMS 10
#define MAX_STORAGES 10
#define MAX_TABLE_NAME 50
#define MAX_STREAM_NAME 62
#define MAX_STORAGE_NAME 31
#define COMMANDS 17
static const uint commandMap[COMMANDS][4] =
{{'c', PID_CODEPAGE, VT_I2},
{'t', PID_TITLE, VT_LPSTR},
{'j', PID_SUBJECT, VT_LPSTR},
{'a', PID_AUTHOR, VT_LPSTR},
{'k', PID_KEYWORDS, VT_LPSTR},
{'o', PID_COMMENTS, VT_LPSTR},
{'p', PID_TEMPLATE, VT_LPSTR},
{'l', PID_LASTAUTHOR, VT_LPSTR},
{'v', PID_REVNUMBER, VT_LPSTR},
{'s', PID_LASTPRINTED, VT_FILETIME},
{'r', PID_CREATE_DTM, VT_FILETIME},
{'q', PID_LASTSAVE_DTM, VT_FILETIME},
{'g', PID_PAGECOUNT, VT_I4},
{'w', PID_WORDCOUNT, VT_I4},
{'h', PID_CHARCOUNT, VT_I4},
{'n', PID_APPNAME, VT_LPSTR},
{'u', PID_SECURITY, VT_I4}};
static const char * commandNames[COMMANDS] =
{"Codepage", "Title", "Subject", "Author", "Keywords", "Comments",
"Template", "Last Saved By", "Revision Number", "Last Printed",
"Create Time/Date", "Last Save Time/Date", "Page Count", "Word Count",
"Character Count", "Creating Application", "Security"};
static void parseDate(LPCWSTR value, SYSTEMTIME *time)
{
LPWSTR field;
uint len = 4*sizeof(WCHAR);
if (lstrlenW(value) != 19) return;
field = malloc(len + sizeof(WCHAR));
if (field == NULL) return;
memcpy(field, value, len);
field[4] = L'\0';
time->wYear = atoiW(field);
len = 2 * sizeof(WCHAR);
memcpy(field, &(value[5]), len);
field[2] = '\0';
time->wMonth = atoiW(field);
memcpy(field, &(value[8]), len);
time->wDay = atoiW(field);
memcpy(field, &(value[11]), len);
time->wHour = atoiW(field);
memcpy(field, &(value[14]), len);
time->wMinute = atoiW(field);
memcpy(field, &(value[17]), len);
time->wSecond = atoiW(field);
free(field);
}
static BOOL msiinfoDisplayProperties(LPWSTR dbfile)
{
MSIHANDLE dbhandle, infohandle;
uint i, r, dataType;
INT iVal;
FILETIME ftVal;
SYSTEMTIME sysTime;
LPWSTR szVal = NULL;
DWORD size;
r = MsiOpenDatabaseW(dbfile, (LPWSTR) MSIDBOPEN_READONLY, &dbhandle);
if (r != ERROR_SUCCESS)
{
return FALSE;
}
r = MsiGetSummaryInformationW(dbhandle, 0, 0, &infohandle);
if (r != ERROR_SUCCESS)
{
return FALSE;
}
for (i = 0; i < COMMANDS; i++)
{
MsiSummaryInfoGetPropertyW(infohandle, commandMap[i][1], &dataType,
&iVal, &ftVal, szVal, &size);
wprintf(L"%-24s", commandNames[i]);
if (dataType == VT_LPSTR)
{
if (szVal!=NULL) wprintf(L"%ls (%d)\n", szVal, lstrlenW(szVal));
else wprintf(L"\n");
}
else if (dataType == VT_FILETIME)
{
FileTimeToSystemTime(&ftVal, &sysTime);
wprintf(L"%04d/%02d/%02d %02d:%02d:%02d\n", sysTime.wYear, sysTime.wMonth,
sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
}
else
{
wprintf(L"%d\n", iVal);
}
}
MsiCloseHandle(infohandle);
return TRUE;
}
static BOOL msiinfoUpdateProperty(MSIHANDLE infoHandle, uint property, uint dataType, LPCWSTR value)
{
uint r;
int iVal = 0;
FILETIME ftVal;
SYSTEMTIME sysTime = {0};
LPCWSTR szVal = NULL;
if (dataType == VT_LPSTR) szVal = value;
else if (dataType == VT_FILETIME)
{
parseDate(value, &sysTime);
SystemTimeToFileTime(&sysTime, &ftVal);
}
else
iVal = atoiW(value);
r = MsiSummaryInfoSetPropertyW(infoHandle, property, dataType, iVal, &ftVal, szVal);
if (r != ERROR_SUCCESS)
{
wprintf(L"Problem updating property: %d %d %d %d\n", r == ERROR_DATATYPE_MISMATCH, r == ERROR_FUNCTION_FAILED, ERROR_UNKNOWN_PROPERTY, ERROR_UNSUPPORTED_TYPE);
return FALSE;
}
return TRUE;
}
static void usage(void)
{
WINE_MESSAGE(
"Usage: msiinfo {database} [[-b]-d] {options} {data}\n"
"\nOptions:\n"
" -c <cp> Specify codepage\n"
" -t <title> Specify title\n"
" -j <subject> Specify subject\n"
" -a <author> Specify author\n"
" -k <keywords> Specify keywords\n"
" -o <comment> Specify comments\n"
" -p <template> Specify template\n"
" -l <author> Specify last author\n"
" -v <revno> Specify revision number\n"
" -s <date> Specify last printed date\n"
" -r <date> Specify creation date\n"
" -q <date> Specify date of last save\n"
" -g <pages> Specify page count\n"
" -w <words> Specify word count\n"
" -h <chars> Specify character count\n"
" -n <appname> Specify application which created the database\n"
" -u <security> Specify security (0: none, 2: read only (rec.) 3: read only (enforced)\n");
}
int wmain(int argc, WCHAR *argv[])
{
WCHAR *dbfile = NULL;
uint i = 0;
MSIHANDLE dbhandle, infohandle;
uint r;
LPWSTR value = 0;
if (argc > 1)
{
dbfile = argv[1];
argv++; argc--;
}
if (argc == 1)
{
msiinfoDisplayProperties(dbfile);
return 0;
}
r = MsiOpenDatabaseW(dbfile, (LPWSTR) MSIDBOPEN_TRANSACT, &dbhandle);
if (r != ERROR_SUCCESS) return 1;
r = MsiGetSummaryInformationW(dbhandle, 0, 20, &infohandle);
if (r != ERROR_SUCCESS) return 2;
while (argv[1] && argv[1][0] == '-')
{
switch (argv[1][1])
{
case '?':
case 'h':
usage();
return 0;
default:
for (i = 0; i < COMMANDS; i++)
{
if (commandMap[i][0] == argv[1][1])
{
argv++; argc--;
value = argv[1];
msiinfoUpdateProperty(infohandle, commandMap[i][1], commandMap[i][2], value);
break;
}
}
break;
}
argv++; argc--;
}
MsiSummaryInfoPersist(infohandle);
MsiDatabaseCommit(dbhandle);
MsiCloseHandle(dbhandle);
msiinfoDisplayProperties(dbfile);
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment