//+-------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1992. // // File: funcs.cxx // // Contents: Generic DocFile support functions // // Functions: ModeToTFlags // CheckName // VerifyPerms // // History: 22-Jan-92 DrewB Created // //--------------------------------------------------------------- #include #pragma hdrstop #include //+-------------------------------------------------------------- // // Function: ModeToDFlags, private // // Synopsis: Translates STGM flags to DF flags // // Arguments: [dwModeFlags] // // Returns: DF_* // // History: 04-Feb-92 DrewB Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_ModeToDFlags) #endif DFLAGS ModeToDFlags(DWORD const dwModeFlags) { DFLAGS df; olDebugOut((DEB_ITRACE, "In ModeToDFlags(%lX)\n", dwModeFlags)); if ((dwModeFlags & STGM_TRANSACTED) == 0) df = DF_DIRECT; else df = DF_TRANSACTED; if ((dwModeFlags & STGM_TRANSACTED) && (dwModeFlags & STGM_PRIORITY) == 0 && (dwModeFlags & STGM_DENY) != STGM_SHARE_DENY_WRITE && (dwModeFlags & STGM_DENY) != STGM_SHARE_EXCLUSIVE) df |= DF_INDEPENDENT; switch(dwModeFlags & STGM_RDWR) { case STGM_READ: df |= DF_READ; break; case STGM_WRITE: df |= DF_WRITE; break; case STGM_READWRITE: df |= DF_READWRITE; break; default: olAssert(FALSE); break; } switch(dwModeFlags & STGM_DENY) { case STGM_SHARE_DENY_READ: df |= DF_DENYREAD; break; case STGM_SHARE_DENY_WRITE: df |= DF_DENYWRITE; break; case STGM_SHARE_EXCLUSIVE: df |= DF_DENYALL; break; // Default is deny none } if (dwModeFlags & STGM_PRIORITY) df |= DF_PRIORITY; #ifdef USE_NOSNAPSHOT #ifdef USE_NOSNAPSHOT_ALWAYS //This makes all transacted-writeable !deny-write instances no-snapshot, // for testing. if ((dwModeFlags & STGM_TRANSACTED) && !(df & DF_DENYWRITE) && (df & DF_WRITE)) { df |= DF_NOSNAPSHOT; df &= ~DF_INDEPENDENT; } #else if (dwModeFlags & STGM_NOSNAPSHOT) { df |= DF_NOSNAPSHOT; df &= ~DF_INDEPENDENT; } #endif //USE_NOSNAPSHOT_ALWAYS #endif //USE_NOSNAPSHOT #ifdef USE_NOSCRATCH #ifdef USE_NOSCRATCH_ALWAYS //This makes everything NOSCRATCH, for testing. if ((dwModeFlags & STGM_TRANSACTED) && (df & DF_WRITE)) df |= DF_NOSCRATCH; #else if (dwModeFlags & STGM_NOSCRATCH) df |= DF_NOSCRATCH; #endif #endif #if WIN32 == 300 if (dwModeFlags & STGM_EDIT_ACCESS_RIGHTS) df |= DF_ACCESSCONTROL; #endif olDebugOut((DEB_ITRACE, "Out ModeToDFlags => %lX\n", df)); return df; } //+-------------------------------------------------------------- // // Function: DFlagsToMode, private // // Synopsis: Converts the read/write/denials/transacted/priority // to STGM flags // // Arguments: [df] - DFlags // // Returns: STGM flags // // History: 24-Jul-92 DrewB Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_DFlagsToMode) #endif DWORD DFlagsToMode(DFLAGS const df) { DWORD dwMode; olDebugOut((DEB_ITRACE, "In DFlagsToMode(%X)\n", df)); if (P_READ(df)) if (P_WRITE(df)) dwMode = STGM_READWRITE; else dwMode = STGM_READ; else if (P_WRITE(df)) dwMode = STGM_WRITE; // Must have either read or write, so no else if (P_DENYREAD(df)) if (P_DENYWRITE(df)) dwMode |= STGM_SHARE_EXCLUSIVE; else dwMode |= STGM_SHARE_DENY_READ; else if (P_DENYWRITE(df)) dwMode |= STGM_SHARE_DENY_WRITE; else dwMode |= STGM_SHARE_DENY_NONE; if (P_TRANSACTED(df)) dwMode |= STGM_TRANSACTED; if (P_PRIORITY(df)) dwMode |= STGM_PRIORITY; if (P_NOSCRATCH(df)) dwMode |= STGM_NOSCRATCH; #ifdef USE_NOSNAPSHOT if (P_NOSNAPSHOT(df)) dwMode |= STGM_NOSNAPSHOT; #endif olDebugOut((DEB_ITRACE, "Out DFlagsToMode\n")); return dwMode; } //+-------------------------------------------------------------- // // Function: VerifyPerms, private // // Synopsis: Checks flags to see if they are valid // // Arguments: [grfMode] - Permissions // // Returns: Appropriate status code // // History: 19-Mar-92 DrewB Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_VerifyPerms) #endif SCODE VerifyPerms(DWORD grfMode) { SCODE sc = S_OK; olDebugOut((DEB_ITRACE, "In VerifyPerms(%lX)\n", grfMode)); // Check for valid flags if ((grfMode & STGM_RDWR) > STGM_READWRITE || (grfMode & STGM_DENY) > STGM_SHARE_DENY_NONE || (grfMode & ~(STGM_RDWR | STGM_DENY | STGM_DIRECT | STGM_TRANSACTED | STGM_PRIORITY | STGM_CREATE | STGM_CONVERT | #ifdef USE_NOSCRATCH STGM_NOSCRATCH | #endif #ifdef USE_NOSNAPSHOT #ifndef DISABLE_NOSNAPSHOT STGM_NOSNAPSHOT | #endif #endif #if WIN32 >= 300 STGM_EDIT_ACCESS_RIGHTS | #endif STGM_FAILIFTHERE | STGM_DELETEONRELEASE))) olErr(EH_Err, STG_E_INVALIDFLAG); // If priority is specified... if (grfMode & STGM_PRIORITY) { #ifndef REF // Make sure no priority-denied permissions are specified if ((grfMode & STGM_RDWR) == STGM_WRITE || (grfMode & STGM_RDWR) == STGM_READWRITE || (grfMode & STGM_TRANSACTED)) olErr(EH_Err, STG_E_INVALIDFLAG); #else return STG_E_INVALIDFUNCTION; #endif //!REF } #ifdef REF if (grfMode & STGM_TRANSACTED) { return STG_E_INVALIDFUNCTION; } #endif //REF // Check to make sure only one existence flag is specified // FAILIFTHERE is zero so it can't be checked if ((grfMode & (STGM_CREATE | STGM_CONVERT)) == (STGM_CREATE | STGM_CONVERT)) olErr(EH_Err, STG_E_INVALIDFLAG); // If not transacted and not priority, you can either be // read-only deny write or read-write deny all if ((grfMode & (STGM_TRANSACTED | STGM_PRIORITY)) == 0) { if ((grfMode & STGM_RDWR) == STGM_READ) { // we're asking for read-only access if ((grfMode & STGM_DENY) != STGM_SHARE_EXCLUSIVE && (grfMode & STGM_DENY) != STGM_SHARE_DENY_WRITE) { // Can't allow others to have write access olErr(EH_Err, STG_E_INVALIDFLAG); } } else { // we're asking for write access if ((grfMode & STGM_DENY) != STGM_SHARE_EXCLUSIVE) { // Can't allow others to have any access olErr(EH_Err, STG_E_INVALIDFLAG); } } } #ifdef USE_NOSCRATCH if (grfMode & STGM_NOSCRATCH) { if (((grfMode & STGM_RDWR) == STGM_READ) || ((grfMode & STGM_TRANSACTED) == 0)) { olErr(EH_Err, STG_E_INVALIDFLAG); } } #endif #ifdef USE_NOSNAPSHOT if (grfMode & STGM_NOSNAPSHOT) { if (((grfMode & STGM_DENY) == STGM_SHARE_EXCLUSIVE) || ((grfMode & STGM_DENY) == STGM_SHARE_DENY_WRITE) || ((grfMode & STGM_TRANSACTED) == 0) || ((grfMode & STGM_NOSCRATCH) != 0) || ((grfMode & STGM_CREATE) != 0) || ((grfMode & STGM_CONVERT) != 0)) { olErr(EH_Err, STG_E_INVALIDFLAG); } } #endif olDebugOut((DEB_ITRACE, "Out VerifyPerms\n")); // Fall through EH_Err: return sc; } //+-------------------------------------------------------------- // // Function: CheckName, public // // Synopsis: Checks name for illegal characters and length // // Arguments: [pwcsName] - Name // // Returns: Appropriate status code // // History: 11-Feb-92 DrewB Created // 04-Dec-95 SusiA Optimized // //--------------------------------------------------------------- #ifdef OLEWIDECHAR SCODE CheckName(WCHAR const *pwcsName) { LPCWSTR pChar; //Each character's position in the array is detrmined by its ascii numeric //value. ":" is 58, so bit 58 of the array will be 1 if ":" is illegal. //32bits per position in the array, so 58/32 is in Invalid[1]. //58%32 = 28th bit ( 0x04000000 ) in Invalid[1]. /* Invalid characters: : / ! \ */ static ULONG const Invalid[128/32] = {0x00000000,0x04008002,0x10000000,0x00000000}; SCODE sc = STG_E_INVALIDNAME; olDebugOut((DEB_ITRACE, "In CheckName(%ws)\n", pwcsName)); __try { for (pChar = (LPCWSTR)pwcsName; pChar <= (LPCWSTR) &pwcsName[CWCMAXPATHCOMPLEN]; pChar++) { if (*pChar == L'\0') { sc = S_OK; break; // Success } // Test to see if this is an invalid character if (*pChar < 128 && // All values above 128 are valid (Invalid[*pChar / 32] & (1 << (*pChar % 32))) != 0) // check to see if this character's bit is set { break; // Failure: invalid Char } } } __except (EXCEPTION_EXECUTE_HANDLER) { } olDebugOut((DEB_ITRACE, "Out CheckName\n")); return sc; } #endif #ifdef EMPTYCOPYTO //+-------------------------------------------------------------- // // Function: DeleteIStorageContents, public // // Synopsis: Deletes all entries in an IStorage // // Arguments: [pstg] - IStorage // // Returns: Appropriate status code // // History: 07-May-92 DrewB Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_DeleteIStorageContents) // Expdf_CopyTo_TEXT #endif SCODE DeleteIStorageContents(IStorage *pstg) { SCODE sc; IEnumSTATSTG *penm; IStorage *pstgTmp; STATSTG sstg; olDebugOut((DEB_ITRACE, "In DeleteIStorageContents(%p)\n", pstg)); olChk(pstg->EnumElements(0, NULL, 0, &penm)); for (;;) { olChkTo(EH_penm, penm->Next(1, &sstg, NULL)); if (S_FALSE == sc) break; if (REAL_STGTY(sstg.type)) { // This entry is an embedded DocFile, recurse olChkTo(EH_pwcsName, pstg->OpenStorage(sstg.pwcsName, NULL, STGM_READ | STGM_WRITE | STGM_DENY_READ | STGM_DENY_WRITE, NULL, 0, &pstgTmp)); olChkTo(EH_OpenStorage, DeleteIStorageContents(pstgTmp)); olVerSucc(pstgTmp->Release()); } olChkTo(EH_pwcsName, pstg->DestroyElement(sstg.pwcsName)); TaskMemFree(sstg.pwcsName); } olVerSucc(penm->Release()); olDebugOut((DEB_ITRACE, "Out DeleteIStorageContents\n")); return S_OK; EH_OpenStorage: olVerSucc(pstgTmp->Release()); EH_pwcsName: TaskMemFree(sstg.pwcsName); EH_penm: olVerSucc(penm->Release()); EH_Err: return sc; } #endif //+-------------------------------------------------------------- // // Function: ValidateSNB, private // // Synopsis: Validates SNB memory // // Arguments: [snb] - SNB // // Returns: Appropriate status code // // History: 10-Jun-92 DrewB Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_ValidateSNB) // #endif SCODE ValidateSNB(SNBW snb) { SCODE sc; olDebugOut((DEB_ITRACE, "In ValidateSNB(%p)\n", snb)); for (;;) { olChk(ValidatePtrBuffer(snb)); if (*snb == NULL) break; olChk(ValidateNameW(*snb, CWCMAXPATHCOMPLEN)); snb++; } olDebugOut((DEB_ITRACE, "Out ValidateSNB\n")); return S_OK; EH_Err: return sc; } //+-------------------------------------------------------------- // // Function: CopySStreamToSStream // // Synopsis: Copies the contents of a stream to another stream // // Arguments: [psstFrom] - Stream to copy from // [psstTo] - Stream to copy to // // Returns: Appropriate status code // // History: 13-Sep-91 DrewB Created // // Notes: This function may fail due to out of memory. It // may not be used by callers who must not fail due // to out of memory. // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_CopySStreamToSStream) #endif SCODE CopySStreamToSStream(PSStream *psstFrom, PSStream *psstTo) { BYTE *pbBuffer = NULL; SCODE sc; ULONG cbRead, cbWritten, cbSize, cbPos; // We're allowed to fail due to out of memory olMem(pbBuffer = (BYTE *) DfMemAlloc(STREAMBUFFERSIZE)); // Set destination size for contiguity psstFrom->GetSize(&cbSize); olChk(psstTo->SetSize(cbSize)); // Copy between streams cbPos = 0; for (;;) { olChk(psstFrom->ReadAt(cbPos, pbBuffer, STREAMBUFFERSIZE, (ULONG STACKBASED *)&cbRead)); if (cbRead == 0) // EOF break; olChk(psstTo->WriteAt(cbPos, pbBuffer, cbRead, (ULONG STACKBASED *)&cbWritten)); if (cbRead != cbWritten) olErr(EH_Err, STG_E_WRITEFAULT); cbPos += cbWritten; } EH_Err: DfMemFree(pbBuffer); return sc; } //+--------------------------------------------------------------------------- // // Function: dfwcsnicmp, public // // Synopsis: wide character string compare that interoperates with what // we did on 16-bit windows. // // Arguments: [wcsa] -- First string // [wcsb] -- Second string // [len] -- Length to compare to // // Returns: > 0 if wcsa > wcsb // < 0 if wcsa < wcsb // 0 is wcsa == wcsb // // History: 11-May-95 PhilipLa Created // 22-Nov-95 SusiA Optimize comparisons // // Notes: This function is necessary because on 16-bit windows our // wcsnicmp function converted everything to uppercase and // compared the strings, whereas the 32-bit runtimes convert // everything to lowercase and compare. This means that the // sort order is different for string containing [\]^_` // //---------------------------------------------------------------------------- int dfwcsnicmp(const WCHAR *wcsa, const WCHAR *wcsb, size_t len) { if (!len) return 0; while (--len && *wcsa && ( *wcsa == *wcsb || CharUpperW((LPWSTR)*wcsa) == CharUpperW((LPWSTR)*wcsb))) { wcsa++; wcsb++; } return (int)CharUpperW((LPWSTR)*wcsa) - (int)CharUpperW((LPWSTR)*wcsb); } //+-------------------------------------------------------------- // // Function: NameInSNB, private // // Synopsis: Determines whether the given name is in the SNB // // Arguments: [dfn] - Name // [snb] - SNB // // Returns: S_OK or S_FALSE // // History: 19-Mar-92 DrewB Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_NameInSNB) #endif SCODE NameInSNB(CDfName const *dfn, SNBW snb) { SCODE sc = S_FALSE; olDebugOut((DEB_ITRACE, "In NameInSNB(%ws, %p)\n", dfn, snb)); TRY { for (; *snb; snb++) if ((lstrlenW(*snb)+1)*sizeof(WCHAR) == dfn->GetLength() && #ifdef CASE_SENSITIVE memcmp(dfn->GetBuffer(), *snb, dfn->GetLength()) == 0) #else dfwcsnicmp((WCHAR *)dfn->GetBuffer(), (WCHAR *)*snb, dfn->GetLength()/sizeof(WCHAR)) == 0) #endif { sc = S_OK; break; } } CATCH(CException, e) { sc = e.GetErrorCode(); } END_CATCH olDebugOut((DEB_ITRACE, "Out NameInSNB\n")); return sc; } //+--------------------------------------------------------------------------- // // Function: Win32ErrorToScode, public // // Synopsis: Map a Win32 error into a corresponding scode, remapping // into Facility_Storage if appropriate. // // Arguments: [dwErr] -- Win32 error to map // // Returns: Appropriate scode // // History: 22-Sep-93 PhilipLa Created // //---------------------------------------------------------------------------- #ifdef WIN32 SCODE Win32ErrorToScode(DWORD dwErr) { olAssert((dwErr != NO_ERROR) && aMsg("Win32ErrorToScode called on NO_ERROR")); SCODE sc = STG_E_UNKNOWN; switch (dwErr) { case ERROR_INVALID_FUNCTION: sc = STG_E_INVALIDFUNCTION; break; case ERROR_FILE_NOT_FOUND: sc = STG_E_FILENOTFOUND; break; case ERROR_PATH_NOT_FOUND: sc = STG_E_PATHNOTFOUND; break; case ERROR_TOO_MANY_OPEN_FILES: sc = STG_E_TOOMANYOPENFILES; break; case ERROR_ACCESS_DENIED: case ERROR_NETWORK_ACCESS_DENIED: sc = STG_E_ACCESSDENIED; break; case ERROR_INVALID_HANDLE: sc = STG_E_INVALIDHANDLE; break; case ERROR_NOT_ENOUGH_MEMORY: sc = STG_E_INSUFFICIENTMEMORY; break; case ERROR_NO_MORE_FILES: sc = STG_E_NOMOREFILES; break; case ERROR_WRITE_PROTECT: sc = STG_E_DISKISWRITEPROTECTED; break; case ERROR_SEEK: sc = STG_E_SEEKERROR; break; case ERROR_WRITE_FAULT: sc = STG_E_WRITEFAULT; break; case ERROR_READ_FAULT: sc = STG_E_READFAULT; break; case ERROR_SHARING_VIOLATION: sc = STG_E_SHAREVIOLATION; break; case ERROR_LOCK_VIOLATION: sc = STG_E_LOCKVIOLATION; break; case ERROR_HANDLE_DISK_FULL: case ERROR_DISK_FULL: sc = STG_E_MEDIUMFULL; break; case ERROR_FILE_EXISTS: case ERROR_ALREADY_EXISTS: sc = STG_E_FILEALREADYEXISTS; break; case ERROR_INVALID_PARAMETER: sc = STG_E_INVALIDPARAMETER; break; case ERROR_INVALID_NAME: case ERROR_BAD_PATHNAME: case ERROR_FILENAME_EXCED_RANGE: sc = STG_E_INVALIDNAME; break; case ERROR_INVALID_FLAGS: sc = STG_E_INVALIDFLAG; break; default: sc = WIN32_SCODE(dwErr); break; } return sc; } #endif