Erweiterte DateiInfos auslesen (Dateikommentar)
-
Hallo,
das sollte weiterhelfen: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/stg/stg/storing_property_sets.asp
-
.. ich glaub COM ist hier der einzigste Weg .. werd was posten wenns klappt
-
Das denk ich auch
hier gibts ein paar gute samples: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/stg/stg/samples.asp
-
http://www.codeguru.com/activex/olefile.shtml
ole filemnager
-
Wenn man davon absieht, daß es das einzigste nicht gibt, bist Du auf dem Holzweg. Es gibt natürlich die \005SummaryInformation innerhalb von Compound-Documents. Wenn ich Dich aber richtig verstehe, suchst Du die Informationen, die unter "Dateiinfo" aufgelistet sind. Diese gibt es auch für beispielweise TXT-Files, und das sind nun garantiert keine DOC-Files. Das, was Du da siehst, sind File-Streams. Schau Dir auch das Programm "Streams" an:
http://www.sysinternals.com/ntw2k/source/misc.shtml#Streams
-
Original erstellt von -King-:
Wenn man davon absieht, daß es das einzigste nicht gibt, bist Du auf dem Holzweg.kannst du mir den satz bitte erklären
kapier ich nicht
-
hat sich erledigt, habs kapiert...
-
Einzig kann man nicht steigern. Oder kann etwas noch einziger als einzig sein? Das Einzigste?
Oder meintest Du das mit dem Holzweg?
[edit] Ok, war zu langsam ... [/edit]
[ Dieser Beitrag wurde am 20.01.2003 um 17:10 Uhr von -King- editiert. ]
-
Also ist teste gerade die einzig* gute Streamvariante.. Man muss sich vorstellen dass ein Editor von einer Datei nur den "::$DATA" - Stream
zum editieren anzeigt, blos sind alle Infos, wie letze Zugriffszeit in
anderen Streams versteckt..
mein Problem ist nun das bei mir nur dieser angezeigt wird.Kennt jemand die Funktion
status = NtQueryInformationFile( fileHandle, &ioStatus,
streamInfo, streamInfoSize,
FileStreamInformation ).. kann das an "FileStreamInformation" liegen .. bzw. könnte FileAlignementStream funtzen ??.. die MSDN Doku ist echt dürftig hierfür..
rgs!
-
Sorry, versteh ich nicht. Die Informationen, die Du suchst, liegen im Stream \005SummaryInformation":
//Der Doppelpunkt hinter dem Dateinamen benennt den Stream hStream = CreateFile(TEXT("D:\\test.txt:\005SummaryInformation"), ...);
Das Format scheint das Gleiche zu sein, wie es auch im COM-Stream verwendet wird.
Woltest Du das wissen?
-
Das war eine sehr sehr gute Info.. den Rest sollte ich selbst schaffen..
ne main wird gepostet
-
Property Name Property ID String
Title PID_TITLE 0x00000002 VT_LPSTR
Subject PID_SUBJECT 0x00000003 VT_LPSTR
Author PID_AUTHOR 0x00000004 VT_LPSTR
Keywords PID_KEYWORDS 0x00000005 VT_LPSTR
Comments PID_COMMENTS 0x00000006 VT_LPSTR
Kleine VorabInfo: (IDs im SummaryStream)Template PID_TEMPLATE 0x00000007 VT_LPSTR
Last Saved By PID_LASTAUTHOR 0x00000008 VT_LPSTR
Revision Number PID_REVNUMBER 0x00000009 VT_LPSTR
Total Editing Time PID_EDITTIME 0x0000000A VT_FILETIME (UTC)
Last Printed PID_LASTPRINTED 0x0000000B VT_FILETIME (UTC)
Create Time/Date (*) PID_CREATE_DTM 0x0000000C VT_FILETIME (UTC)
Last saved Time/Date (*) PID_LASTSAVE_DTM 0x0000000D VT_FILETIME (UTC)
-
Aufruf des ganzen: hr=StgOpenStorage ( lpwstr , NULL, STGM_READ | STGM_DIRECT | STGM_PRIORITY, NULL, 0, &pIStorage ); GetSummaryInfo ( pIStorage, &Title , &Subject , &Author , &Keywords , &Comments ); //############################################################## #define UNICODE 1 #include "afx.h" #include "stdafx.h" #include <afxwin.h> #include <windowsx.h> #include <winnls.h> #include <mapinls.h> #include "edk.h" //#include "PostSmpl.h" #include <initguid.h> //#include "freedoc.h" #include "iostream.h" #include <afxres.h> //LPCSTR _lpa = NULL; int _convert = 0; #include <afxconv.h> LPCSTR _lpa = NULL; /* * Data Strcuctures */ typedef GUID FMTID; typedef struct _fmtidoffset { FMTID fmtid; // FMTID for a section DWORD dwOffset; // offset of section from start of stream } FMTIDOFFSET; typedef struct _propsethdr { WORD wByteOrder; // Always 0xFFFE WORD wFormat; // Always 0 DWORD dwOSVer; // Hiword: 0=Win16; 1=Mac; 2=Win32 // Loword: GetVersion() CLSID clsid; // App CLSID DWORD cSections; // Number of sections } PROPSETHDR; typedef DWORD PID; typedef struct _pidoffset { PID pid; // Property ID DWORD dwOffset; // offset of property from start of section } PIDOFFSET; typedef struct _propsectionhdr { DWORD cbSection; // Size of this section DWORD cProps; // Number of properties in this section } PROPSECTIONHDR; /* * Define some of the guids we use */ DEFINE_GUID(FMTID_SumInfo, 0xF29F85E0L, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9); typedef struct _mppidmapiprop { WORD wMapiType; // MAPI Type LPWSTR szW; // MAPI Name } MPPIDMAPIPROP; enum pidSumInfo { PID_TITLE = 2, PID_SUBJECT, PID_AUTHOR, PID_KEYWORDS, PID_COMMENTS, cpidSumInfoMax }; typedef struct _propsetstminfo { LPOLESTR szName; // stream name FMTID const *pfmtid; // FMTID of section to promote INT cmppidmapipropMax; // Mapping for property names MPPIDMAPIPROP *mppidmapiprop; } PROPSETSTMINFO; // Lego workaround - define the symbols for the array WCHAR szTitle[] = L"Title"; WCHAR szSubject[] = L"Subject"; WCHAR szAuthor[] = L"Author"; WCHAR szKeywords[] = L"Keywords"; WCHAR szComments[] = L"Comments"; MPPIDMAPIPROP mppidmapipropSumInfo[] = { { PT_NULL, NULL }, // Dictionary { PT_NULL, NULL }, // Code page { PT_STRING8, szTitle }, { PT_STRING8, szSubject }, { PT_STRING8, szAuthor }, { PT_MV_STRING8, szKeywords }, // Special case VT_LPSTR -> MV { PT_STRING8, szComments } }; OLECHAR szSumInfo[] = OLESTR("\005SummaryInformation"); PROPSETSTMINFO rgpropsetstminfo[] = { {szSumInfo, &FMTID_SumInfo, cpidSumInfoMax, mppidmapipropSumInfo}, {NULL, NULL, 0, NULL} }; // ################################################################### HRESULT SzDupSz(LPCTSTR sz, LPSTR *lppstr) { INT cb = 0; HRESULT hr = NOERROR; if (!sz) return hr; cb = (lstrlen(sz) + 1) * sizeof(TCHAR); if (!SUCCEEDED(hr = MAPIAllocateBuffer(cb, (LPVOID *)lppstr))) return hr; if (!lstrcpy(*lppstr, sz)) return hr; return hr; } // ##################### PARSE KEYWORD FROM varSTERAM ############## SCODE ScParseKeywords(LPSPropValue pval, TCHAR * szDefSep) { SCODE sc= S_OK; LPSTR szKeywords= pval->Value.lpszA; CHAR * pch= szKeywords; CHAR * pchPrev= NULL; LPSTR * rgsz= NULL; LONG cKeywords= 0; LONG isz= 0; TCHAR szSep[3]; BOOL fInWord= FALSE; BOOL fFakeOneWord= FALSE; HRESULT hr= NOERROR; static TCHAR szScParseKeywords1[] = TEXT("intl"); static TCHAR szScParseKeywords2[] = TEXT("sList"); static TCHAR szScParseKeywords3[] = TEXT(","); // Get the list separator character GetProfileString(szScParseKeywords1, szScParseKeywords2, szScParseKeywords3, szSep, sizeof(szSep) / sizeof(TCHAR)); // Default list separator is the space character if (!szDefSep) szDefSep = TEXT(" "); // Loop through the string zero filling non-keywords while (*pch) { #ifdef DBCS if (!FGLeadByte(*pch) && (*pch == szDefSep[0] || *pch == szSep[0])) #else if (*pch == szDefSep[0] || *pch == szSep[0]) #endif { fInWord = FALSE; } else { // If we aren't in a word, we are now if (!fInWord) cKeywords++; fInWord = TRUE; } // Remember this position pchPrev = pch; // Move forward #ifdef DBCS pch = SzGNext(pch); #else pch = AnsiNext(pch); #endif // If we aren't in a word, zap area from our previous position if (!fInWord) ZeroMemory(pchPrev, pch - pchPrev); } // Remove leading and trailing spaces from keywords pch = szKeywords; isz = cKeywords; while (isz) { isz--; // Skip consecutive separators while (!*pch) pch++; if (*pch) { // Zero out leading spaces pchPrev = pch; while (isspace(*pch)) pch = AnsiNext(pch); ZeroMemory(pchPrev, pch - pchPrev); // Blank keyword if (!*pch) { cKeywords--; continue; } // Go to end of string pch = &pch[lstrlen(pch)]; // Zero out trailing spaces pchPrev = AnsiPrev(szKeywords, pch); while (isspace(*pchPrev)) pchPrev = AnsiPrev(szKeywords, pchPrev); pchPrev = AnsiNext(pchPrev); ZeroMemory(pchPrev, pch - pchPrev); } } // Handle denegerate case where we have no keywords. MAPI requires that // there be a value, though, so we fake up a single empty string if (!cKeywords) { cKeywords = 1; fFakeOneWord = TRUE; } // Now that we know how many keywords there are, it's time to allocate // space pval->Value.MVszA.cValues = cKeywords; if (!SUCCEEDED(hr = MAPIAllocateBuffer(cKeywords * sizeof(LPSTR), (LPVOID *)&pval->Value.MVszA.lppszA))) { sc = E_OUTOFMEMORY; goto CleanUp; } rgsz = pval->Value.MVszA.lppszA; if (fFakeOneWord) { if (!SUCCEEDED(hr = SzDupSz((LPSTR) TEXT(""), &rgsz[0]))) sc = E_OUTOFMEMORY; goto CleanUp; } // Find the strings we had left over pch = szKeywords; while (isz < cKeywords) { if (*pch) { // Remember the start of the string and then zoom to the end if ( !SUCCEEDED(hr = SzDupSz(pch, &rgsz[isz++]))) { sc = E_OUTOFMEMORY; goto CleanUp; } while (*pch) #ifdef DBCS pch = SzGNext(pch); #else ++pch; #endif } ++pch; } CleanUp: return sc; } //#################### loadstr ##################################### SCODE ScLoadStr(LPSTREAM pstm, CString *lpcstring) { SCODE sc= S_OK; HRESULT hr= NOERROR; LPSTR lpstr= NULL; DWORD dwSize= 0; // Save string size if (hr = pstm->Read(&dwSize, sizeof(DWORD), NULL)) goto CleanUp; // Allocate space for string and then load the string if (dwSize) // hr = MAPIAllocateBuffer(dwSize, (LPVOID *)&lpstr); lpstr = (LPSTR)malloc(dwSize); else hr = SzDupSz((LPTSTR)TEXT(""), &lpstr); if (!SUCCEEDED(hr)) { sc = E_OUTOFMEMORY; goto CleanUp; } if (dwSize && (hr = pstm->Read(lpstr, dwSize, NULL))) { sc = GetScode(hr); goto CleanUp; } *lpcstring = lpstr; CleanUp: //MAPIFREEBUFFER(lpstr); free(lpstr); return sc; } //################## GETSUMMARY INFO ############################## */ STDAPI GetSummaryInfo ( LPSTORAGE pstg, CString* lpsTitle, CString* lpsSubject, CString* lpsAuthor, CString* lpsKeywords, CString* lpsComments ) { SCODE sc= S_OK; HRESULT hr= NOERROR; PROPSETHDR propsethdr; PROPSECTIONHDR propsectionhdr; FMTIDOFFSET* rgfmtidoffset= NULL; FMTIDOFFSET* pfmtidoffset= NULL; PIDOFFSET* rgpidoffset= NULL; PIDOFFSET* ppidoffset= NULL; PROPSETSTMINFO* ppropsetstminfo = rgpropsetstminfo; // point to summary info part ULONG cb= 0; BOOL fFound= FALSE; BOOL fSumInfoStm= FALSE; LARGE_INTEGER li={0}; DWORD dwType= 0; LPSTREAM pstm= NULL; *lpsTitle = TEXT(""); *lpsSubject = TEXT(""); *lpsAuthor = TEXT(""); *lpsKeywords= TEXT(""); *lpsComments= TEXT(""); // Open the summay info stream /*sc = pstg->OpenStream(ppropsetstminfo->szName, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pstm); */ sc = pstg->OpenStream(ppropsetstminfo->szName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE , 0, &pstm); if (FAILED(sc)) { goto CleanUp; } // Read the header to find out how many sections we need to search if (hr = pstm->Read(&propsethdr, sizeof(propsethdr), NULL)) goto ReadError; if (propsethdr.cSections == 0) goto CleanUp; // Allocate space for the sections list and read it in cb = propsethdr.cSections * sizeof(FMTIDOFFSET); /* if (!SUCCEEDED(hr = MAPIAllocateBuffer(cb, (LPVOID *)&rgfmtidoffset))) { sc = E_OUTOFMEMORY; goto CleanUp; } */ rgfmtidoffset = (FMTIDOFFSET*)malloc(cb); pfmtidoffset = rgfmtidoffset; if (hr = pstm->Read(rgfmtidoffset, cb, NULL)) goto ReadError; // Look for the section with the matching FMTID for (fFound = FALSE; propsethdr.cSections--; ++pfmtidoffset) { if (IsEqualGUID(*ppropsetstminfo->pfmtid, pfmtidoffset->fmtid)) { fFound = TRUE; break; } } if (!fFound) goto CleanUp; // Are we in the SumInfo stream fSumInfoStm = IsEqualGUID(*ppropsetstminfo->pfmtid, FMTID_SumInfo); // Seek to that location in the stream LISet32(li, pfmtidoffset->dwOffset); if (hr = pstm->Seek(li, STREAM_SEEK_SET, NULL)) goto ReadError; // Read the section header to find out how many props we need to read if (hr = pstm->Read(&propsectionhdr, sizeof(propsectionhdr), NULL)) goto ReadError; if (propsectionhdr.cProps == 0) goto CleanUp; // Allocate space for the props list and read it in cb = propsectionhdr.cProps * sizeof(PIDOFFSET); /* if (!SUCCEEDED(hr = MAPIAllocateBuffer(cb, (LPVOID *)&rgpidoffset))) { sc = E_OUTOFMEMORY; goto CleanUp; } */ rgpidoffset = (PIDOFFSET*)malloc(cb); ppidoffset = rgpidoffset; if (hr = pstm->Read(rgpidoffset, cb, NULL)) goto ReadError; // Go through all the properties for (; propsectionhdr.cProps--; ++ppidoffset) { // Seek to the data LISet32(li, ppidoffset->dwOffset + pfmtidoffset->dwOffset); if (hr = pstm->Seek(li, STREAM_SEEK_SET, NULL)) goto ReadError; // Read the type if (hr = pstm->Read(&dwType, sizeof(DWORD), NULL)) goto ReadError; // Load the data hr = NOERROR; switch (ppidoffset->pid) { case PID_TITLE: sc = ScLoadStr(pstm, lpsTitle); break; case PID_SUBJECT: sc = ScLoadStr(pstm, lpsSubject); break; case PID_AUTHOR: sc = ScLoadStr(pstm, lpsAuthor); break; case PID_KEYWORDS: sc = ScLoadStr(pstm, lpsKeywords); break; case PID_COMMENTS: sc = ScLoadStr(pstm, lpsComments); break; default: continue; break; } if (hr) goto ReadError; } goto CleanUp; ReadError: sc = GetScode(hr); CleanUp: free(rgfmtidoffset); free(rgpidoffset); ULRELEASE(pstm); return sc; }
PS. Bitte ändert mein Juniorstatus!)
-
Dein Status hängt soviel ich weiß mit der Anzahl deiner Beiträge zusammen! Also, fleißig schreiben
-
.. warum nicht mit der Größe.. , dann wäre ich doch voll dabei hehe
naja dan werd ich mal eben mein Senf überall dazugeben
so ihr lieben .. zeigt euch mal
:p