windows-nt/Source/XPSP1/NT/com/winole/samples/srvrdemo/file.c
2020-09-26 16:20:57 +08:00

535 lines
13 KiB
C

/*
OLE SERVER DEMO
File.c
This file contains file input/output functions for for the OLE server demo.
(c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
*/
#include <windows.h>
#include <commDlg.h>
#include <ole.h>
#include "srvrdemo.h"
// File signature stored in the file.
#define szSignature "ServerDemo"
#define cchSigLen (10+1)
// Delimiter for fields in the file
#define chDelim ':'
// Default file extension
#define szDefExt "sd"
// File header structure
typedef struct
{
CHAR szSig [cchSigLen];
CHAR chDelim1;
VERSION version;
CHAR chDelim2;
CHAR rgfObjNums [cfObjNums+1];
} HEADER;
// BOOL GetFileSaveFilename (LPSTR lpszFilename);
static VOID InitOfn (OPENFILENAME *pofn);
static BOOL SaveDocIntoFile (PSTR);
static LPOBJ ReadObj (INT fh);
/* CreateDocFromFile
* -----------------
*
* Read a document from the specified file.
*
* LPSTR lpszDoc - Name of the file containing the document
* LHSERVERDOC lhdoc - Handle to the document
* DOCTYPE doctype - In what state the document is created
*
* RETURNS: TRUE if successful, FALSE otherwise
*
* CUSTOMIZATION: Re-implement
* This function will need to be completely re-implemented
* to support your application's file format.
*
*/
BOOL CreateDocFromFile (LPSTR lpszDoc, LHSERVERDOC lhdoc, DOCTYPE doctype)
{
INT fh; // File handle
HEADER hdr;
INT i;
if ((fh =_lopen(lpszDoc, OF_READ)) == -1)
return FALSE;
// Read header from file.
if (_lread(fh, (LPSTR) &hdr, (UINT)sizeof(HEADER)) < sizeof (HEADER))
goto Error;
// Check to see if file is a server demo file.
if (lstrcmp(hdr.szSig, szSignature))
goto Error;
if (hdr.chDelim1 != chDelim)
goto Error;
// Check to see if file was saved under the most recent version.
// Here is where you would handle reading in old versions.
if (hdr.version != version)
goto Error;
if (hdr.chDelim2 != chDelim)
goto Error;
if (!CreateNewDoc (lhdoc, lpszDoc, doctype))
goto Error;
// Get the array indicating which object numbers have been used.
for (i=1; i <= cfObjNums; i++)
docMain.rgfObjNums[i] = hdr.rgfObjNums[i];
// Read in object data.
for (i=0; ReadObj (fh); i++);
if (!i)
{
OLESTATUS olestatus;
fRevokeSrvrOnSrvrRelease = FALSE;
if ((olestatus = RevokeDoc()) > OLE_WAIT_FOR_RELEASE)
goto Error;
else if (olestatus == OLE_WAIT_FOR_RELEASE)
Wait (&fWaitingForDocRelease);
fRevokeSrvrOnSrvrRelease = TRUE;
EmbeddingModeOff();
goto Error;
}
_lclose(fh);
fDocChanged = FALSE;
return TRUE;
Error:
_lclose(fh);
return FALSE;
}
/* OpenDoc
* -------
*
* Prompt the user for which document he wants to open
*
* RETURNS: TRUE if successful, FALSE otherwise.
*
* CUSTOMIZATION: None, except your application may or may not call
* CreateNewObj to create a default object.
*
*/
BOOL OpenDoc (VOID)
{
CHAR szDoc[cchFilenameMax];
BOOL fUpdateLater;
OLESTATUS olestatus;
if (SaveChangesOption (&fUpdateLater) == IDCANCEL)
return FALSE;
if (!GetFileOpenFilename (szDoc))
{
if (fUpdateLater)
{
// The user chose the "Yes, Update" button but the
// File Open dialog box failed for some reason
// (perhaps the user chose Cancel).
// Even though the user chose "Yes, Update", there is no way
// to update a client that does not accept updates
// except when the document is closed.
}
return FALSE;
}
if (fUpdateLater)
{
// The non-standard OLE client did not accept the update when
// we requested it, so we are sending the client OLE_CLOSED now that
// we are closing the document.
SendDocMsg (OLE_CLOSED);
}
fRevokeSrvrOnSrvrRelease = FALSE;
if ((olestatus = RevokeDoc()) > OLE_WAIT_FOR_RELEASE)
return FALSE;
else if (olestatus == OLE_WAIT_FOR_RELEASE)
Wait (&fWaitingForDocRelease);
fRevokeSrvrOnSrvrRelease = TRUE;
EmbeddingModeOff();
if (!CreateDocFromFile (szDoc, 0, doctypeFromFile))
{
MessageBox (hwndMain,
"Reading from file failed.\r\nFile may not be in proper file format.",
szAppName,
MB_ICONEXCLAMATION | MB_OK);
// We already revoked the document, so give the user a new one to edit.
CreateNewDoc (0, "(Untitled)", doctypeNew);
CreateNewObj (FALSE);
return FALSE;
}
fDocChanged = FALSE;
return TRUE;
}
/* ReadObj
* --------
*
* Read the next object from a file, allocate memory for it, and return
* a pointer to it.
*
* int fh - File handle
*
* RETURNS: A pointer to the object
*
* CUSTOMIZATION: Server Demo specific
*
*/
static LPOBJ ReadObj (INT fh)
{
HANDLE hObj = NULL;
LPOBJ lpobj = NULL;
hObj = LocalAlloc (LMEM_MOVEABLE | LMEM_ZEROINIT, sizeof (OBJ));
if (hObj == NULL)
return NULL;
lpobj = (LPOBJ) LocalLock (hObj);
if (lpobj==NULL)
{
LocalFree (hObj);
return NULL;
}
if (_lread(fh, (LPSTR) &lpobj->native, (UINT)sizeof(NATIVE)) < sizeof (NATIVE))
{
LocalUnlock (hObj);
LocalFree (hObj);
return NULL;
}
lpobj->hObj = hObj;
lpobj->oleobject.lpvtbl = &objvtbl;
lpobj->aName = GlobalAddAtom (lpobj->native.szName);
if (!CreateWindow(
"ObjClass",
"Obj",
WS_THICKFRAME | WS_BORDER | WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE ,
lpobj->native.nX,
lpobj->native.nY,
lpobj->native.nWidth,
lpobj->native.nHeight,
hwndMain,
NULL,
hInst,
(LPSTR) lpobj ))
{
LocalUnlock (hObj);
LocalFree (hObj);
return NULL;
}
return lpobj;
}
/* SaveDoc
* -------
*
* Save the document.
*
* CUSTOMIZATION: None
*
*/
BOOL SaveDoc (VOID)
{
if (docMain.doctype == doctypeNew)
return SaveDocAs();
else
{
CHAR szDoc [cchFilenameMax];
GlobalGetAtomName (docMain.aName, szDoc, cchFilenameMax);
return SaveDocIntoFile(szDoc);
}
}
/* SaveDocAs
* ---------
*
* Prompt the user for a filename, and save the document under that filename.
*
* RETURNS: TRUE if successful or user chose CANCEL
* FALSE if SaveDocIntoFile fails
*
* CUSTOMIZATION: None
*
*/
BOOL SaveDocAs (VOID)
{
CHAR szDoc[cchFilenameMax];
BOOL fUpdateLater = FALSE;
CHAR szDocOld[cchFilenameMax];
// If document is embedded, give user a chance to update.
// Save old document name in case the save fails.
if (!GlobalGetAtomName (docMain.aName, szDocOld, cchFilenameMax))
ErrorBox ("Fatal Error: Document name is invalid.");
if (GetFileSaveFilename (szDoc))
{
if (docMain.doctype == doctypeEmbedded)
return SaveDocIntoFile(szDoc);
if (fUpdateLater)
{
// The non-standard OLE client did not accept the update when
// we requested it, so we are sending the client OLE_CLOSED now that
// we are closing the document.
SendDocMsg (OLE_CLOSED);
}
// Set the window title bar.
SetTitle (szDoc, FALSE);
OleRenameServerDoc(docMain.lhdoc, szDoc);
if (SaveDocIntoFile(szDoc))
return TRUE;
else
{ // Restore old name
SetTitle (szDocOld, FALSE);
OleRenameServerDoc(docMain.lhdoc, szDocOld);
return FALSE;
}
}
else // user chose Cancel
return FALSE;
// The user chose the "Yes, Update" button but the
// File Open dialog box failed for some reason
// (perhaps the user chose Cancel).
// Even though the user chose "Yes, Update", there is no way
// to update a non-standard OLE client that does not accept updates
// except when the document is closed.
}
/* SaveDocIntoFile
* ---------------
*
* Save the document into a file whose name is determined from docMain.aName.
*
* RETURNS: TRUE if successful
* FALSE otherwise
*
* CUSTOMIZATION: Re-implement
*
*/
static BOOL SaveDocIntoFile (PSTR pDoc)
{
HWND hwnd;
INT fh; // File handle
LPOBJ lpobj;
HEADER hdr;
INT i;
hwnd = GetWindow (hwndMain, GW_CHILD);
if (!hwnd)
{
ErrorBox ("Could not save NULL file.");
return FALSE;
}
// Get document name.
if ((fh =_lcreat(pDoc, 0)) == -1)
{
ErrorBox ("Could not save file.");
return FALSE;
}
// Fill in header.
lstrcpy (hdr.szSig, szSignature);
hdr.chDelim1 = chDelim;
hdr.version = version;
hdr.chDelim2 = chDelim;
for (i=1; i <= cfObjNums; i++)
hdr.rgfObjNums[i] = docMain.rgfObjNums[i];
// Write header to file.
if (_lwrite(fh, (LPSTR) &hdr, (UINT)sizeof(HEADER)) < sizeof(HEADER))
goto Error; // Error writing file header
// Write each object's native data.
while (hwnd)
{
lpobj = (LPOBJ) GetWindowLong (hwnd, ibLpobj);
if (_lwrite(fh, (LPSTR)&lpobj->native, (UINT)sizeof (NATIVE))
< sizeof(NATIVE))
goto Error; // Error writing file header
hwnd = GetWindow (hwnd, GW_HWNDNEXT);
}
_lclose(fh);
if (docMain.doctype != doctypeEmbedded)
{
docMain.doctype = doctypeFromFile;
OleSavedServerDoc(docMain.lhdoc);
fDocChanged = FALSE;
}
return TRUE;
Error:
_lclose(fh);
ErrorBox ("Could not save file.");
return FALSE;
}
/* Common Dialog functions */
/* InitOfn
* -------
*
* Initialize an OPENFILENAME structure with default values.
* OPENFILENAME is defined in CommDlg.h.
*
*
* CUSTOMIZATION: Change lpstrFilter. You may also customize the common
* dialog box if you wish. (See the Windows SDK documentation.)
*
*/
static VOID InitOfn (OPENFILENAME *pofn)
{
// GetOpenFileName or GetSaveFileName will put the 8.3 filename into
// szFileTitle[].
// SrvrDemo does not use this filename, but rather uses the fully qualified
// pathname in pofn->lpstrFile[].
static CHAR szFileTitle[13];
pofn->Flags = 0;
pofn->hInstance = hInst;
pofn->hwndOwner = hwndMain;
pofn->lCustData = 0;
pofn->lpfnHook = NULL;
pofn->lpstrCustomFilter = NULL;
pofn->lpstrDefExt = szDefExt;
// lpstrFile[] is the initial filespec that appears in the edit control.
// Must be set to non-NULL before calling the common dialog box function.
// On return, lpstrFile[] will contain the fully-qualified pathname
// corresponding to the file the user chose.
pofn->lpstrFile = NULL;
pofn->lpstrFilter = "Server Demo (*." szDefExt ")\0*." szDefExt "\0" ;
// lpstrFileTitle[] will contain the user's chosen filename without a path.
pofn->lpstrFileTitle = szFileTitle;
pofn->lpstrInitialDir= NULL;
// Title Bar. NULL means use default title.
pofn->lpstrTitle = NULL;
pofn->lpTemplateName = NULL;
pofn->lStructSize = sizeof (OPENFILENAME);
pofn->nFilterIndex = 1L;
pofn->nFileOffset = 0;
pofn->nFileExtension = 0;
pofn->nMaxFile = cchFilenameMax;
pofn->nMaxCustFilter = 0L;
}
/* GetFileOpenFilename
* -------------------
*
* Call the common dialog box function GetOpenFileName to get a file name
* from the user when the user chooses the "File Open" menu item.
*
* LPSTR lpszFilename - will contain the fully-qualified pathname on exit.
*
* RETURNS: TRUE if successful, FALSE otherwise.
*
* CUSTOMIZATION: None
*
*/
BOOL GetFileOpenFilename (LPSTR lpszFilename)
{
OPENFILENAME ofn;
InitOfn (&ofn);
ofn.Flags |= OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
// Create initial filespec.
wsprintf (lpszFilename, "*.%s", (LPSTR) szDefExt);
// Have the common dialog function return the filename in lpszFilename.
ofn.lpstrFile = lpszFilename;
if (!GetOpenFileName (&ofn))
return FALSE;
return TRUE;
}
/* GetFileSaveFilename
* -------------------
*
* Call the common dialog box function GetSaveFileName to get a file name
* from the user when the user chooses the "File Save As" menu item, or the
* "File Save" menu item for an unnamed document.
*
* LPSTR lpszFilename - will contain the fully-qualified pathname on exit.
*
* RETURNS: TRUE if successful, FALSE otherwise.
*
* CUSTOMIZATION: None
*
*/
BOOL GetFileSaveFilename (LPSTR lpszFilename)
{
OPENFILENAME ofn;
InitOfn (&ofn);
ofn.Flags |= OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
// Create initial filespec.
wsprintf (lpszFilename, "*.%s", (LPSTR) szDefExt);
// Have the common dialog function return the filename in lpszFilename.
ofn.lpstrFile = lpszFilename;
if (!GetSaveFileName (&ofn))
return FALSE;
return TRUE;
}