697 lines
24 KiB
C++
697 lines
24 KiB
C++
|
//+----------------------------------------------------------------------------// File: DF2T.CXX
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1991 - 1992.
|
||
|
//
|
||
|
// Contents: utility program for converting a Docfile to a directory tree.
|
||
|
// Given a Docfile,it is walked with an enumerator and each
|
||
|
// embedded IStorage creates a directory in the specified
|
||
|
// destination tree while each IStream creates a file within
|
||
|
// the appropriate directory. Finally, a tree compare is
|
||
|
// performed on the source and destination trees.
|
||
|
//
|
||
|
// Classes: IStorage - Container class
|
||
|
// IStream - Contained stream class
|
||
|
// IEnumSTATSTG - Enumerator class for IStorages
|
||
|
//
|
||
|
// Command line: df2c -f/-b -(n)ameofDocfile -(s)rcTree -(d)estTree -T -W
|
||
|
// -f forward conversion (docfile --> tree)
|
||
|
// -b backward conversion (tree --> docfile)
|
||
|
// -n name for root docfile
|
||
|
// -s name of the source directory tree
|
||
|
// -d name of the destination directory tree
|
||
|
// -t specifies STGM_TRANSACTED mode
|
||
|
// -w specifies STGM_SHARE_DENY_WRITE mode for root docfile
|
||
|
//
|
||
|
// -f and -b cannot be both specified in one command.
|
||
|
//
|
||
|
// The default conversion is from Docfile to tree.
|
||
|
// Therefore, -n and -d(est) must be specified when forward
|
||
|
// conversion -f is used. Otherwise, -b should be accompanied
|
||
|
// by -s(rc) and -n(doc).
|
||
|
//
|
||
|
// This utility defaults to running in DIRECT mode so that all
|
||
|
// operations at all levels are performed immediately on the
|
||
|
// base copy of the root docfile.
|
||
|
//
|
||
|
// With the -T switch, this runs in STGM_TRANSACTED mode for
|
||
|
// all IStorage creation and instantiation so that scratch
|
||
|
// streams are created and committed, but only made permanent
|
||
|
// in the persistent version by Commit of the root docfile.
|
||
|
//
|
||
|
// With the -W switch, this runs in STGM_TRANSACTED mode
|
||
|
// with STGM_SHARE_DENY_WRITE for root docfile creation and
|
||
|
// instantiation so that operations are performed on the base
|
||
|
// copy of the docfile.
|
||
|
//
|
||
|
// Requires: Windows 3.x. MSF.DLL and DOCFILE.DLL should be in same dir
|
||
|
// as executable or in \windows\system
|
||
|
//
|
||
|
// Returns: 0 if successful, exits with error code otherwise
|
||
|
//
|
||
|
// Notes: uses whcar and 'mbtowcs' conversions for wide char support
|
||
|
// returns STG_E_NOTCURRENT if docfile-to-be-created
|
||
|
// already exists.
|
||
|
//
|
||
|
// Created: RichE, January 13, 1992 Original program
|
||
|
// Revised: t-chrisy, June 25, 1992 convert the test program to a utility
|
||
|
// dftc.cxx --> df2t.cxx
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <dos.h>
|
||
|
#include <direct.h>
|
||
|
|
||
|
#include "w4ctsupp.hxx"
|
||
|
|
||
|
#define WILD_CARD "\\*.*"
|
||
|
#define BACK_SLASH "\\"
|
||
|
#define NS_INCL (STGTY_STORAGE | STGTY_STREAM)
|
||
|
#define FIND_ATTRS _A_SUBDIR | _A_NORMAL | _A_RDONLY | _A_HIDDEN
|
||
|
#define FILE_BUF_SIZE 32768 // msf is optimized for file size of 4K or 512bytes
|
||
|
#define DOCTOTREE 0
|
||
|
#define TREETODOC 1
|
||
|
|
||
|
//function prototypes
|
||
|
void CopyTreeToDocfile(IStorage *pstgParent);
|
||
|
void CopyDocfileToTree(IStorage *pstgParent, TCHAR *ptcsDFName);
|
||
|
void CopyFileToStream(IStorage *pstgParent, char *FileName);
|
||
|
void CopyStreamToFile(IStorage *pstgParent, TCHAR *ptcsStreamName);
|
||
|
int GetOptions(int argc, char *argv[]);
|
||
|
void Usage(char *pszProgName);
|
||
|
|
||
|
//buffers for file/dir path calls and docfile name (default assignments)
|
||
|
char szDestDocfile[_MAX_PATH + 1] = "";
|
||
|
char szSrcPath[_MAX_PATH + 1] = "";
|
||
|
char szDestPath[_MAX_PATH + 1] = "";
|
||
|
int iSrcPathEnd = sizeof(_MAX_PATH); //length minus terminating '\0'
|
||
|
int iDestPathEnd = sizeof(_MAX_PATH);
|
||
|
|
||
|
//buffers for converting to/from wide characters
|
||
|
TCHAR wcsWideName[_MAX_PATH + 1];
|
||
|
char szName[_MAX_PATH + 1];
|
||
|
|
||
|
//modifiers to flags for root and child docfiles (GetOptions may modify)
|
||
|
DWORD dwRootFlags = STGM_READWRITE | STGM_SHARE_DENY_WRITE;
|
||
|
DWORD dwChildFlags = STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
|
||
|
|
||
|
void utMemFree(void *pv)
|
||
|
{
|
||
|
IMalloc FAR* pMalloc;
|
||
|
if (SUCCEEDED(GetScode(CoGetMalloc(MEMCTX_TASK, &pMalloc))))
|
||
|
{
|
||
|
pMalloc->Free(pv);
|
||
|
pMalloc->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
// Function: main, public
|
||
|
//
|
||
|
// Synopsis: main body of program, controls overall flow
|
||
|
//
|
||
|
// Effects: initialize. Depending on the direction of converionsn,
|
||
|
// call functions to create a tree, given a DocFile;
|
||
|
// call functions to create a DocFile, given a tree.
|
||
|
//
|
||
|
// Created: RichE January 13, 1992 original program
|
||
|
// Revised: t-chrisy June 25, 1992 modified to convert docfile to tree;
|
||
|
// and vice versa.
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
void main(int argc, char *argv[])
|
||
|
{
|
||
|
IStorage *pstgDest = NULL;
|
||
|
SCODE scRc;
|
||
|
short ret;
|
||
|
|
||
|
#if WIN32 == 300
|
||
|
if (FAILED(scRc = GetScode(CoInitializeEx(NULL, COINIT_MULTITHREADED))))
|
||
|
#else
|
||
|
if (FAILED(scRc = GetScode(CoInitialize(NULL))))
|
||
|
#endif
|
||
|
{
|
||
|
fprintf(stderr, "CoInitialize failed with sc = %lx\n", scRc);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
ret=GetOptions(argc, argv);
|
||
|
if (ret==DOCTOTREE)
|
||
|
{
|
||
|
tprintf(bDestOut, "Converting Docfile to tree....\n");
|
||
|
if ((!strcmp(szDestDocfile,"\0"))||(!strcmp(szDestPath,"\0")))
|
||
|
{
|
||
|
tprintf(bDestOut, "Invalid switches used.\n");
|
||
|
tprintf(bDestOut,
|
||
|
"If -f is indicated, -n and -d must also be specified.\n");
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tprintf(bDestOut, "Converting a directory tree to Docfile....\n");
|
||
|
if ((!strcmp(szDestDocfile,"\0")||(!strcmp(szSrcPath,"\0"))))
|
||
|
{
|
||
|
tprintf(bDestOut, "Invalid switches used.\n");
|
||
|
tprintf(bDestOut,
|
||
|
"If -b is chosen, -s and -n must also be specified.\n");
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dwRootFlags & STGM_TRANSACTED)
|
||
|
{
|
||
|
tprintf(bDestOut, "STGM_TRANSACTED mode ");
|
||
|
if ((dwRootFlags & 0x70) == STGM_SHARE_EXCLUSIVE)
|
||
|
{
|
||
|
tprintf(bDestOut, "with STGM_SHARE_EXCLUSIVE");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tprintf(bDestOut, "without STGM_SHARE_EXCLUSIVE");
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tprintf(bDestOut, "STGM_DIRECT mode (with STGM_SHARE_EXCLUSIVE)");
|
||
|
}
|
||
|
tprintf(bDestOut, " operation\n");
|
||
|
|
||
|
MakeWide(wcsWideName, szDestDocfile);
|
||
|
|
||
|
if (ret==DOCTOTREE) // Docfile to tree...
|
||
|
{
|
||
|
MakePath(szDestPath);
|
||
|
CopyDocfileToTree((IStorage *) NULL, wcsWideName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Create root docfile with specified mode, nuke if already exists
|
||
|
tprintf(bDestOut, "Create root docfile %s\n", szDestDocfile);
|
||
|
scRc = GetScode(StgCreateDocfile(wcsWideName,
|
||
|
dwRootFlags | STGM_CREATE, 0,
|
||
|
&pstgDest));
|
||
|
tprintf(bDestOut, "Returned %lu\n", scRc);
|
||
|
tprintf(bDestOut, "Root docfile %s %s, pointer %p\n", szDestDocfile,
|
||
|
pstgDest == NULL ? "FALSE" : "TRUE", pstgDest);
|
||
|
if (pstgDest == NULL || FAILED(scRc))
|
||
|
{
|
||
|
ErrExit(DEST_LOG, scRc, "Error creating root docfile %s\n",
|
||
|
szDestDocfile);
|
||
|
}
|
||
|
CopyTreeToDocfile(pstgDest);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
// Function: CopyTreeToDocfile, private
|
||
|
//
|
||
|
// Synopsis: traverses and reads source tree and creates docfile image
|
||
|
//
|
||
|
// Effects: for each directory in source tree, an IStorage is created, for each
|
||
|
// file, a contained stream is created. this function is recursive.
|
||
|
//
|
||
|
// Arguments: [pstgParent] - current parent IStorage for new containees
|
||
|
//
|
||
|
// Created: RichE, January 13, 1992
|
||
|
// Revised: RichE March 5, 1992 Df APIs to method calls
|
||
|
// Revised: RichE March 6, 1992 TRANSACTED mode operation
|
||
|
// Revised: RichE March 17, 1992 convert to OLE interfaces
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
void CopyTreeToDocfile(IStorage *pstgParent)
|
||
|
{
|
||
|
struct find_t FileInfo;
|
||
|
SCODE scRc;
|
||
|
USHORT usEndOfBasePath;
|
||
|
IStorage *pstgChild;
|
||
|
|
||
|
// Save pointer to base of pure path at this level
|
||
|
usEndOfBasePath = strlen(szSrcPath) + 1;
|
||
|
|
||
|
scRc = _dos_findfirst(strcat(szSrcPath, WILD_CARD), FIND_ATTRS, &FileInfo);
|
||
|
|
||
|
while (scRc==0)
|
||
|
{
|
||
|
// If not '.' or '..' directories
|
||
|
if (FileInfo.name[0] != '.')
|
||
|
{
|
||
|
// Restore pure path and add current file/dir name to it
|
||
|
szSrcPath[usEndOfBasePath] = NIL;
|
||
|
strcat(szSrcPath, FileInfo.name);
|
||
|
if (FileInfo.attrib == _A_SUBDIR)
|
||
|
{
|
||
|
MakeWide(wcsWideName, FileInfo.name);
|
||
|
// Create new IStorage inside current one,
|
||
|
// use dir name for name
|
||
|
tprintf(bDestOut,
|
||
|
"Create embedded DF %s inside pstgParent %p\n",
|
||
|
szSrcPath, pstgParent);
|
||
|
scRc = GetScode(pstgParent->CreateStorage(wcsWideName,
|
||
|
dwChildFlags |
|
||
|
STGM_FAILIFTHERE,
|
||
|
0, 0,
|
||
|
&pstgChild));
|
||
|
tprintf(bDestOut, "Returned: %lu, pointer = %p\n",
|
||
|
scRc, pstgChild);
|
||
|
|
||
|
if (pstgChild == NULL || FAILED(scRc))
|
||
|
{
|
||
|
ErrExit(DEST_LOG, scRc,
|
||
|
"Error creating child IStorage %s\n",
|
||
|
FileInfo.name);
|
||
|
}
|
||
|
CopyTreeToDocfile(pstgChild);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CopyFileToStream(pstgParent, FileInfo.name);
|
||
|
}
|
||
|
}
|
||
|
scRc = _dos_findnext(&FileInfo);
|
||
|
}
|
||
|
if (dwRootFlags & STGM_TRANSACTED)
|
||
|
{
|
||
|
tprintf(bDestOut, "Committing pstgParent %p\n", pstgParent);
|
||
|
if (scRc = GetScode(pstgParent->Commit(STGC_ONLYIFCURRENT)))
|
||
|
{
|
||
|
ErrExit(DEST_LOG, scRc, "Error committing IStorage %p\n",
|
||
|
pstgParent);
|
||
|
}
|
||
|
}
|
||
|
tprintf(bDestOut, "Releasing pstgParent %p\n", pstgParent);
|
||
|
pstgParent->Release();
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
// Function: CopyFileToStream, private
|
||
|
//
|
||
|
// Synopsis: copies supplied file to stream inside of parent IStorage
|
||
|
//
|
||
|
// Arguments: [pstgParent] - parent IStorage for stream created
|
||
|
// [FileName] - name of source file to copy to stream
|
||
|
//
|
||
|
// Created: RichE, January 13, 1992
|
||
|
// Revised: RichE March 5, 1992 Df APIs to method calls
|
||
|
// Revised: RichE March 6, 1992 TRANSACTED mode operation
|
||
|
// Revised: RichE March 15, 1992 streams no longer TRANSACTED
|
||
|
// Revised: RichE March 17, 1992 convert to OLE interfaces
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
void CopyFileToStream(IStorage *pstgParent, char *FileName)
|
||
|
{
|
||
|
IStream *pstmStream = NULL;
|
||
|
FILE *FileToCopy;
|
||
|
SCODE scRc;
|
||
|
ULONG cNumRead;
|
||
|
ULONG cNumWritten;
|
||
|
BYTE *FileBuf;
|
||
|
|
||
|
tprintf(bDestOut, " File %s\n", szSrcPath);
|
||
|
FileToCopy = fopen(szSrcPath, "rb");
|
||
|
if (FileToCopy == NULL)
|
||
|
{
|
||
|
ErrExit(DEST_LOG, ERR, "Cannot open file %s\n", szSrcPath);
|
||
|
}
|
||
|
|
||
|
MakeWide(wcsWideName, FileName);
|
||
|
|
||
|
// Create a stream inside parent IStorage
|
||
|
tprintf(bDestOut,
|
||
|
"Create embedded stream inside parent pstgParent = %p\n",
|
||
|
pstgParent);
|
||
|
scRc = GetScode(pstgParent->CreateStream(wcsWideName, STGM_STREAM |
|
||
|
STGM_FAILIFTHERE, 0, 0,
|
||
|
&pstmStream));
|
||
|
tprintf(bDestOut, "Returned: %lu, pointer = %p\n", scRc, pstmStream);
|
||
|
if (pstmStream == NULL || FAILED(scRc))
|
||
|
{
|
||
|
ErrExit(DEST_LOG, scRc, "Error creating stream %s\n", szSrcPath);
|
||
|
}
|
||
|
|
||
|
FileBuf = (BYTE * ) Allocate(FILE_BUF_SIZE * sizeof(BYTE));
|
||
|
|
||
|
//while still reading from source file, write what was just read to Stream
|
||
|
while (cNumRead = fread(FileBuf, 1, FILE_BUF_SIZE, FileToCopy))
|
||
|
{
|
||
|
if (ferror(FileToCopy))
|
||
|
{
|
||
|
ErrExit(DEST_LOG, ERR, "Error during stream read of %s\n",
|
||
|
szSrcPath);
|
||
|
}
|
||
|
|
||
|
tprintf(bDestOut, "Try Stream write of %lu bytes on stream %p\n",
|
||
|
cNumRead, pstmStream);
|
||
|
scRc = GetScode(pstmStream->Write(FileBuf, cNumRead, &cNumWritten));
|
||
|
tprintf(bDestOut, "Returned: %lu, bytes written %lu\n",
|
||
|
scRc, cNumWritten);
|
||
|
if (cNumWritten != cNumRead)
|
||
|
{
|
||
|
tprintf(bDestOut, "Write: scRc = %lu, cNumWritten = %lu, ",
|
||
|
scRc, cNumWritten);
|
||
|
tprintf(bDestOut, "cNumRead = %lu\n", cNumRead);
|
||
|
}
|
||
|
|
||
|
if (FAILED(scRc))
|
||
|
{
|
||
|
ErrExit(DEST_LOG, ERR, "Error writing stream %p\n", pstmStream);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
tprintf(bDestOut, "Releasing stream %p\n", pstmStream);
|
||
|
pstmStream->Release();
|
||
|
|
||
|
fclose(FileToCopy);
|
||
|
free(FileBuf);
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------// Function: CopyDocfileToTree, private
|
||
|
//
|
||
|
// Synopsis: enumerates and reads docfile and creates directory tree
|
||
|
//
|
||
|
// Effects: for each child IStorage in the root docfile, a subdir is created,
|
||
|
// for each child stream, a file is created. this function is
|
||
|
// recursive.
|
||
|
//
|
||
|
// Arguments: [pstgParent] - current parent IStorage for reading containees
|
||
|
// [ptcsDFName] - name of IStorage to instantiate
|
||
|
//
|
||
|
// Created: RichE, January 13, 1992
|
||
|
// Revised: RichE March 5, 1992 Df APIs to method calls
|
||
|
// Revised: RichE March 6, 1992 TRANSACTED mode operation
|
||
|
// Revised: RichE March 17, 1992 convert to OLE interfaces
|
||
|
// Revised: t-chrisy June 30, 1992 removed the section on unlinking docfile
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
void CopyDocfileToTree(IStorage *pstgParent, TCHAR *ptcsDFName)
|
||
|
{
|
||
|
IStorage *pstgSrc = NULL;
|
||
|
IEnumSTATSTG *penmWalk;
|
||
|
USHORT usEndOfBasePath;
|
||
|
SCODE scRc;
|
||
|
STATSTG sstg;
|
||
|
int iRc;
|
||
|
|
||
|
// Add back slash & save pointer to base of pure path at this level
|
||
|
strcat(szDestPath, BACK_SLASH);
|
||
|
usEndOfBasePath = strlen(szDestPath);
|
||
|
|
||
|
MakeSingle(szName, ptcsDFName);
|
||
|
|
||
|
// If not first call (parent != NULL) then instantiate child IStorage with
|
||
|
// method call, else instantiate root docfile via Df API call
|
||
|
if (pstgParent != NULL)
|
||
|
{
|
||
|
tprintf(bDestOut, "Get embedded IStorage %s in parent %p\n",
|
||
|
szName, pstgParent);
|
||
|
scRc = GetScode(pstgParent->OpenStorage(ptcsDFName, NULL, dwChildFlags,
|
||
|
NULL, 0, &pstgSrc));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tprintf(bDestOut, "Instantiate root docfile %s\n", szName);
|
||
|
dwRootFlags |= STGM_READ;
|
||
|
scRc = GetScode(StgOpenStorage(ptcsDFName, NULL, dwRootFlags, NULL,
|
||
|
0, &pstgSrc));
|
||
|
}
|
||
|
|
||
|
tprintf(bDestOut, "Return code: %lu, IStorage pointer %p\n",
|
||
|
scRc, pstgSrc);
|
||
|
if (pstgSrc == NULL || FAILED(scRc))
|
||
|
{
|
||
|
ErrExit(DEST_LOG, scRc, "Error instantiating IStorage %s\n", szName);
|
||
|
}
|
||
|
|
||
|
// Get an enumerator on the IStorage we just instantiated
|
||
|
scRc = GetScode(pstgSrc->EnumElements(0, NULL, 0, &penmWalk));
|
||
|
tprintf(bDestOut, "Got enumerator %p on IStorage %p, returned %lu\n",
|
||
|
penmWalk, pstgSrc, scRc);
|
||
|
if (penmWalk == NULL || FAILED(scRc))
|
||
|
{
|
||
|
ErrExit(DEST_LOG, scRc,
|
||
|
"Error obtaining enumerator for IStorage %p\n", pstgSrc);
|
||
|
}
|
||
|
|
||
|
// Loop until GetNext returns other than S_OK, then break out of loop
|
||
|
while (TRUE)
|
||
|
{
|
||
|
if (GetScode(penmWalk->Next(1, &sstg, NULL)) != S_OK)
|
||
|
{
|
||
|
tprintf(bDestOut, "No more to enumerate with enumerator %p\n",
|
||
|
penmWalk);
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MakeSingle(szName, sstg.pwcsName);
|
||
|
tprintf(bDestOut, "Got item type %lu, Name %s, w/enumerator %p\n",
|
||
|
sstg.type, szName, penmWalk);
|
||
|
|
||
|
// Restore to path + BACK_SLASH and add file/dir name to DestPath
|
||
|
szDestPath[usEndOfBasePath] = NIL;
|
||
|
strcat(szDestPath, szName);
|
||
|
tprintf(bDestOut, "Path Name: %s is ", szDestPath);
|
||
|
if (sstg.type == STGTY_STORAGE)
|
||
|
{
|
||
|
tprintf(bDestOut, "STGTY_STORAGE\n");
|
||
|
iRc = _mkdir(szDestPath);
|
||
|
tprintf(bDestOut,
|
||
|
"Trying to make directory %s, returned %d\n",
|
||
|
szDestPath, iRc);
|
||
|
CopyDocfileToTree(pstgSrc, sstg.pwcsName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tprintf(bDestOut, "STGTY_STREAM\n");
|
||
|
CopyStreamToFile(pstgSrc, sstg.pwcsName);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
utMemFree(sstg.pwcsName);
|
||
|
}
|
||
|
|
||
|
tprintf(bDestOut, "Releasing enumerator %p\n", penmWalk);
|
||
|
penmWalk->Release();
|
||
|
}
|
||
|
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
// Function: CopyStreamToFile, private
|
||
|
//
|
||
|
// Synopsis: copies supplied embedded stream to file in current dubdir
|
||
|
//
|
||
|
// Arguments: [pstgParent] - parent IStorage for stream to copy
|
||
|
// [ptcsStreamName] - name of stream to copy to file
|
||
|
//
|
||
|
// Created: RichE, January 13, 1992
|
||
|
// Revised: RichE March 5, 1992 Df APIs to method calls
|
||
|
// Revised: RichE March 6, 1992 TRANSACTED mode operation
|
||
|
// Revised: RichE March 15, 1992 streams no longer TRANSACTED
|
||
|
// Revised: RichE March 17, 1992 convert to OLE interfaces
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
void CopyStreamToFile(IStorage *pstgParent, TCHAR *ptcsStreamName)
|
||
|
{
|
||
|
IStream *pstmStream = NULL;
|
||
|
FILE *FileToWrite;
|
||
|
ULONG cNumRead = 1;
|
||
|
ULONG cNumWritten;
|
||
|
BYTE *FileBuf;
|
||
|
SCODE scRc;
|
||
|
|
||
|
tprintf(bDestOut, "Copying embedded stream to file %s\n", szDestPath);
|
||
|
|
||
|
// Instantiate named stream within parent IStorage
|
||
|
tprintf(bDestOut, "Get stream in parent %p\n", pstgParent);
|
||
|
scRc = GetScode(pstgParent->OpenStream(ptcsStreamName, NULL, STGM_STREAM,
|
||
|
0, &pstmStream));
|
||
|
tprintf(bDestOut, "Returned: %lu, stream pointer %p\n", scRc, pstmStream);
|
||
|
if (pstmStream == NULL || FAILED(scRc))
|
||
|
{
|
||
|
ErrExit(DEST_LOG, scRc, "Error opening stream %s\n", szDestPath);
|
||
|
}
|
||
|
|
||
|
FileToWrite = fopen(szDestPath, "wb");
|
||
|
if (FileToWrite == NULL)
|
||
|
{
|
||
|
ErrExit(DEST_LOG, ERR, "Cannot open file %s\n", szDestPath);
|
||
|
}
|
||
|
|
||
|
FileBuf = (BYTE * ) Allocate(FILE_BUF_SIZE * sizeof(BYTE));
|
||
|
|
||
|
// While still reading Stream, write what was just read to file.
|
||
|
tprintf(bDestOut, "Starting to read stream %p\n", pstmStream);
|
||
|
while (cNumRead > 0)
|
||
|
{
|
||
|
scRc = GetScode(pstmStream->Read(FileBuf, FILE_BUF_SIZE, &cNumRead));
|
||
|
tprintf(bDestOut, "Read %lu bytes from stream %p, returned %lu\n",
|
||
|
cNumRead, pstmStream, scRc);
|
||
|
if (FAILED(scRc))
|
||
|
{
|
||
|
ErrExit(DEST_LOG, scRc, "Error reading stream %p\n", pstmStream);
|
||
|
}
|
||
|
cNumWritten = (ULONG)fwrite(FileBuf, 1, (size_t)cNumRead, FileToWrite);
|
||
|
if (ferror(FileToWrite))
|
||
|
{
|
||
|
ErrExit(DEST_LOG, ERR, "Error writing to file %s\n", szDestPath);
|
||
|
}
|
||
|
|
||
|
if (cNumWritten != cNumRead)
|
||
|
{
|
||
|
tprintf(bDestOut, "Fwrite: cNumRead = %lu, cNumWritten = %lu\n",
|
||
|
cNumRead, cNumWritten);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
tprintf(bDestOut, "Attempting to release stream %p in IStorage %p\n",
|
||
|
pstmStream, pstgParent);
|
||
|
pstmStream->Release();
|
||
|
|
||
|
fclose(FileToWrite);
|
||
|
free(FileBuf);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
// Function: GetOptions, private
|
||
|
// Returns: DOCTOTREE or TREETODOC to indicate the direction of conversion.
|
||
|
//
|
||
|
// Synopsis: parses command line and sets global program options/variables
|
||
|
//
|
||
|
// Arguments: [argc] and [**argv] passed from main() function
|
||
|
//
|
||
|
// Modifies: [szSrcPath, szDestPath, szDestDocfile]
|
||
|
//
|
||
|
// Created: RichE, January 13, 1992
|
||
|
// Revised: RichE, March 15, 1992 added -T and -W switches
|
||
|
// Revised: RichE, March 19, 1992 fixed bug displaying error usage
|
||
|
// Revised: t-chrisy, June 25, 1992 added -f and -b switches
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
int GetOptions(int argc, char *argv[])
|
||
|
{
|
||
|
char *pszArg;
|
||
|
char *pszProgName;
|
||
|
BOOL ArgsOK = TRUE;
|
||
|
short ret=DOCTOTREE;
|
||
|
|
||
|
// Bump past command name (argv[0])
|
||
|
pszProgName = *argv++;
|
||
|
|
||
|
// For each command line arg, if it begins with a '-' or '/' check the
|
||
|
// next letter for a valid argument. return error for invalid args
|
||
|
|
||
|
while ((pszArg = *argv++) != NULL)
|
||
|
{
|
||
|
if (*pszArg == '-' || *pszArg == '/')
|
||
|
{
|
||
|
switch (tolower(*(++pszArg)))
|
||
|
{
|
||
|
case 'w':
|
||
|
dwRootFlags |= STGM_TRANSACTED;
|
||
|
dwChildFlags |= STGM_TRANSACTED;
|
||
|
break;
|
||
|
case 't':
|
||
|
dwRootFlags |= STGM_TRANSACTED;
|
||
|
dwChildFlags |= STGM_TRANSACTED;
|
||
|
break;
|
||
|
|
||
|
case 's':
|
||
|
strcpy(szSrcPath, ++pszArg);
|
||
|
iSrcPathEnd = strlen(pszArg);
|
||
|
break;
|
||
|
|
||
|
case 'd':
|
||
|
strcpy(szDestPath, ++pszArg);
|
||
|
iDestPathEnd = strlen(pszArg);
|
||
|
break;
|
||
|
|
||
|
case 'z':
|
||
|
LogFile(++pszArg,LOG_INIT);
|
||
|
break;
|
||
|
|
||
|
case 'y':
|
||
|
SetDebugMode(tolower(*(++pszArg)));
|
||
|
break;
|
||
|
|
||
|
case 'n':
|
||
|
if (strlen(++pszArg) <= _MAX_PATH)
|
||
|
{
|
||
|
strcpy(szDestDocfile, pszArg);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tprintf(DEST_LOG, "Dest DocFile Name too long: %s\n",
|
||
|
pszArg);
|
||
|
tprintf(DEST_LOG, "Max len = %d\n", _MAX_PATH);
|
||
|
tprintf(DEST_LOG, "Specified len = %d\n", strlen(pszArg));
|
||
|
ArgsOK = FALSE;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'f':
|
||
|
// Docfile to tree
|
||
|
dwRootFlags &= ~0x03; // clear access bits
|
||
|
dwRootFlags |= STGM_READ;
|
||
|
ret=DOCTOTREE;
|
||
|
break;
|
||
|
|
||
|
case 'b':
|
||
|
// Tree to docfile
|
||
|
dwRootFlags &= ~0x70;
|
||
|
dwRootFlags |= STGM_SHARE_EXCLUSIVE;
|
||
|
ret=TREETODOC;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
ArgsOK = FALSE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
ArgsOK = FALSE;
|
||
|
|
||
|
if (ArgsOK == FALSE)
|
||
|
{
|
||
|
tprintf(DEST_LOG,
|
||
|
"Invalid command line argument: %s\n", --pszArg);
|
||
|
Usage(pszProgName);
|
||
|
}
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
// Function: Usage, private
|
||
|
//
|
||
|
// Synopsis: displays program syntax and example and exits with error
|
||
|
//
|
||
|
// Arguments: [pszProgramName] - name of this executable file for error usage
|
||
|
//
|
||
|
// Created: RichE, January 15, 1992
|
||
|
// Revised: t-chrisy, June 30, 1992 Added -f and -b options.
|
||
|
//+----------------------------------------------------------------------------
|
||
|
|
||
|
void Usage(char *pszProgName)
|
||
|
{
|
||
|
|
||
|
tprintf(DEST_ERR, "Usage: %s\n", pszProgName);
|
||
|
tprintf(DEST_ERR, " [-f] - forward conversion"
|
||
|
"(docfile-->tree) DEFAULT\n");
|
||
|
tprintf(DEST_ERR, " -n and -d must be specified.");
|
||
|
tprintf(DEST_ERR, " [-b] - backward conversion"
|
||
|
"(tree-->docfile)\n");
|
||
|
tprintf(DEST_ERR, " -s and -n must be specified.");
|
||
|
tprintf(DEST_ERR, " [-sSRCDIR] \n");
|
||
|
tprintf(DEST_ERR, " [-nDOCFILENAME] \n");
|
||
|
tprintf(DEST_ERR, " [-dDESTDIR] \n");
|
||
|
tprintf(DEST_ERR, " [-t] - for transacted mode\n");
|
||
|
tprintf(DEST_ERR, " [-w] - for deny write mode\n");
|
||
|
ErrExit(DEST_ERR, ERR, " ex: %df2t -b -sc:\\dos -nd:\\docfile.dfl\n",
|
||
|
pszProgName);
|
||
|
}
|