// nntpdrv.idl : IDL source for nntpdrv.dll // // This file will be processed by the MIDL tool to // produce the type library (nntpdrv.tlb) and marshalling code. import "oaidl.idl"; import "ocidl.idl"; // // -------------- Interfaces implemented by the Server -------------- // interface INntpServer; interface INNTPPropertyBag; interface INewsTreeIterator; interface INewsTree; interface INntpComplete; interface INntpDriver; interface INntpDriverSearch; interface INntpSearchResults; // // Server access request bits // cpp_quote("#define NNTP_ACCESS_READ 0x0001") cpp_quote("#define NNTP_ACCESS_POST 0x0002") cpp_quote("#define NNTP_ACCESS_CREATE_SUBFOLDER 0x0004") cpp_quote("#define NNTP_ACCESS_REMOVE_SUBFOLDER 0x0008") cpp_quote("#define NNTP_ACCESS_REMOVE_FOLDER 0x0010") cpp_quote("#define NNTP_ACCESS_REMOVE 0x0020") cpp_quote("#define NNTP_ACCESS_EDIT_FOLDER 0x0040") cpp_quote("#define NNTP_ACCESS_EDIT 0x0080") // // Connect flag bits // cpp_quote("#define NNTP_CONNECT_UPGRADE 0x0001") // // Server mode, driver can inquire about server mode to determine' // what he should do during DecorateNewsTree // cpp_quote("#define NNTP_SERVER_NORMAL 0x0001") cpp_quote("#define NNTP_SERVER_STANDARD_REBUILD 0x0002") cpp_quote("#define NNTP_SERVER_CLEAN_REBUILD 0x0003") typedef struct { BYTE cLen; BYTE pbStoreId[256]; } STOREID; typedef DWORD GROUPID; // // This interface exposes server functionality // [ object, uuid(c7bae7b4-dee3-11d1-94cf-00c04fa379f1), helpstring("INntpDriver Interface"), ] interface INntpServer : IUnknown { // // find the primary groupid/articleid for an article given the secondary // groupid/articleid // // arguments: // pgroupSecondary - the property bag for the secondary crosspost // artidSecondary - the article ID for the secondary crosspost // ppgroupPrimary - gets filled in with the property bag for the primary // crosspost. the caller should Release() this when // they are done with it. // fStorePrimary - if TRUE then return the primary article for the store // that owns pgroupSecondary // partidPrimary - the article id for the primary crosspost // // returns (through completion object): // S_OK - found primary // S_FALSE - the values given were the primary // or an error code // [local] void FindPrimaryArticle([in] INNTPPropertyBag *pGroupSecondary, [in] DWORD artidSecondary, [out] INNTPPropertyBag **ppgroupPrimary, [out] DWORD *partidPrimary, [in] BOOL fStorePrimary, [in] INntpComplete *pCompletion, [in] INntpComplete *pProtocolComplete ); // // Create the entries in the hash tables for a new article. // [local] void CreatePostEntries([in] CHAR *pszMessageId, [in] DWORD iHeaderLength, [in] STOREID *pStoreId, [in] BYTE cGroups, [in] INNTPPropertyBag **rgpGroups, [in,out] DWORD *rgArticleIds, [in] BOOL fAllocArtId, [in] INntpComplete *pCompletion); // // Create the entries in the hash tables for a new article. // [local] void DeleteArticle([in] CHAR *pszMessageId, [in] INntpComplete *pCompletion); // // This tells the driver what rebuild mode the server is in // The returned value should be NNTP_SERVER_NORMAL, NNTP_SERVER // _STANDARD_REBUILD or NNTP_SERVER_CLEAN_REBUILD // [local] DWORD QueryServerMode(); // // Tells whether should skip empty dir when rebuild // [local] BOOL SkipNonLeafDirWhenRebuild(); // // Should I continue the rebuild ? Anybody has cancelled the rebuild ? // [local] BOOL ShouldContinueRebuild(); // // Is this message id in the server ( article table ) ? // [local] BOOL MessageIdExist( CHAR *szMessageId ); // // Set rebuild last error // [local] void SetRebuildLastError( DWORD err ); // // Obtain article number for each newsgroups. // [local] void AllocArticleNumber([in] BYTE cGroups, [in] INNTPPropertyBag **rgpGroups, [in,out] DWORD *rgArticleIds, [in] INntpComplete *pCompletion); // // Return whether this is a Slave server, and the pickup dir // [local] BOOL IsSlaveServer( [out] WCHAR* pwszPickupDir, [out] LPVOID lpvContext); }; // // this property bag is used to represent data in the newsgroups // [ object, uuid(f5ad0d78-af9f-11d1-862e-00c04fb960ea) ] interface INNTPPropertyBag : IUnknown { // // put a BLOB property into the table. this is also used for string // properties // [local] HRESULT PutBLOB( [in] DWORD dwID, [in] DWORD cbValue, [in,size_is(cbValue)] BYTE *pbValue); // // get a BLOB property from the table. this is also used for string // properties // [local] HRESULT GetBLOB( [in] DWORD dwID, [in] BYTE *pbValue, [in,out] DWORD *pcbValue); // // put a dword property into the table // [local] HRESULT PutDWord( [in] DWORD dwID, [in] DWORD dwValue); // // get a dword property from the table // [local] HRESULT GetDWord( [in] DWORD dwID, [out] DWORD *pdwValue); // // put an interface pointer into the table // // interfaces can only be used with properties that are runtime only. // [local] HRESULT PutInterface( [in] DWORD dwID, [in] IUnknown *punkValue); // // get an interface pointer from the table // [local] HRESULT GetInterface( [in] DWORD dwID, [out] IUnknown **ppunkValue); // // put a bool to the table // [local] HRESULT PutBool( DWORD dwID, BOOL fValue ); // // get a bool from the table // HRESULT GetBool( DWORD dwID, BOOL *pfValue); // // remove a property from the property bag // [local] HRESULT RemoveProperty( [in] DWORD dwID); }; [ object, uuid(53f10148-afa8-11d1-862e-00c04fb960ea) ] interface INewsTreeIterator : IUnknown { // // are we at the front or back of the list? returns S_OK if we are // at the beginning or end, and S_FALSE otherwise. // [local] BOOL IsBegin(); [local] BOOL IsEnd(); // // go to the next or previousgroup // [local] void Next(); [local] void Prev(); // // get this group // [local] HRESULT Current( [out] INNTPPropertyBag **ppGroup, INntpComplete *pProtocolComplete ); }; [ object, uuid(9d2de8dc-afc4-11d1-862e-00c04fb960ea) ] interface INewsTree : IUnknown { // // given a group ID find the matching group // [local] HRESULT FindGroupByID( [in] DWORD dwGroupID, [out] INNTPPropertyBag **ppNewsgroupProps, [in] INntpComplete *pProtocolComplete ); // // given a group name find the matching group. if the group doesn't // exist and fCreateIfNotExist is set then a new group will be created. // the new group won't be available until CommitGroup() is called. // if the group is Release'd before CommitGroup was called then it // won't be added. // [local] HRESULT FindOrCreateGroupByName( [in] LPSTR pszGroupName, [in] BOOL fCreateIfNotExist, [out] INNTPPropertyBag **ppNewsgroupProps, [in] INntpComplete *pProtocolComplete, [in] GROUPID groupid, [in] BOOL fSetGroupId ); // // add a new group to the newstree // [local] HRESULT CommitGroup( [in] INNTPPropertyBag *pNewsgroupProps ); // // remove an entry // [local] HRESULT RemoveGroupByID( [in] DWORD dwGroupID); [local] HRESULT RemoveGroupByName( [in] LPSTR pszGroupName, [in] LPVOID lpContext); // // enumerate across the list of keys. // [local] HRESULT GetIterator( [out] INewsTreeIterator **punkIterator // BUGBUG -- need to add filtering options ); // // this function will be used by drivers to make sure that they // are adding newsgroups that they properly own. // HRESULT LookupVRoot([in] LPSTR pszGroup, [out] INntpDriver **ppDriver); // // Get a pointer to the owning server object // [local] HRESULT GetNntpServer( [out] INntpServer **ppNntpServer ); }; // // IIS side completion object interface // [ object, uuid(5EFC52FC-EADF-11d1-9212-00C04FA322A5), helpstring("INntpComplete Interface"), ] interface INntpComplete : IUnknown { // This is the base interface for all IIS side completion // objects. The base interface has only one interface // method: SetResult. This method may be overwritten by // derived class methods to carry out different implementation // for different completions. [local] void SetResult( [in] HRESULT hr ); [local] void ReleaseBag( INNTPPropertyBag *pPropBag ); }; // // -------------- Interfaces implemented by the Driver -------------- // // // Driver implementaion interface that implements actual // driver functionality. // Returned by INntpDriverPrepare after successfully connected // to Exchange store. // [ object, uuid(ADD1050F-99C5-11D1-9128-00C04FC30A64), helpstring("INntpDriver Interface"), ] interface INntpDriver : IUnknown { typedef DWORD ARTICLEID; /////////////////////////////////////////////////////////////////////////// // ***** initialize, terminate, config methods: /////////////////////////////////////////////////////////////////////////// // Purpose: // Initialize the driver // Parameters: // pszVRootPath - virtual root path this driver interface maps to // ie. Nntpsvc/1/root/alt // pLookup - a pointer to the server's ILookup interface // pNewsTree - a pointer to the server's INewsTree interface // pdwNDS - Return status of current NNTP driver after Initialize() // Comments: // o Register change notification (ie directory pickup) // o Initialize Epoxy (once per Exchange store type) // o Detect if the other side of NNTP DLL is running (Exchange only) // o Initialize other global objects/interfaces (such as IMAIL, Async lib, etc) // o strVRootPath to obtain directory path (FS) or store name (Exchange) from VRoot // o Ilookup and InewsTree services are for notification operations on the store // as well as expiration. // o From metabase retrieve expiration policy // o Setup expiration // o WHAT OTHER PARAMETERS NEEDED/TASKS PERFORMED HERE - POSSIBLY: // o May setup metabase change notification to pickup expiration policy changes [local] HRESULT Initialize( [in] LPCWSTR pszVRootPath, [in] LPCSTR pszGroupPrefix, [in] IUnknown *punkMetabase, [in] INntpServer *pServer, [in] INewsTree *pINewsTree, [in] LPVOID lpvContext, [out] DWORD *pdwNDS, [in] HANDLE hToken ); // Purpose: // Detach the driver from protocol and cleanup // Parameters: // None // Comments: // o Un-register change notification. // o Un-initialize Epoxy, if last driver interface pointer to Terminate() // o Terminate expiration // o Other tasks? HRESULT Terminate( [out] DWORD *pdwNDS ); // Purpose: // Get the status of current NNTP driver // Parameters: // pdwNDS - NNTP_DRIVER_STATUS code // Comments: // o Used to get status of current NNTP driver, include: // STORE_UP, STORE_DOWN, EPOXY_ERROR, etc HRESULT GetDriverStatus( [out] DWORD *pdwNDS ); /////////////////////////////////////////////////////////////////////////// // ***** store change notification process method /////////////////////////////////////////////////////////////////////////// // Purpose: // Handle change notification from the store // Parameters: // punkSOCChangeList - List of changes originated from store // Comment // o Serve as change notification process function dispatcher // o Owns a list of changes coming from the store HRESULT StoreChangeNotify( [in] IUnknown *punkSOCChangeList ); /////////////////////////////////////////////////////////////////////////// // ***** article posting methods: /////////////////////////////////////////////////////////////////////////// // Purpose: // Commit the post // Parameters: // See separate spec from awetmore // Returned error code from completion object: // S_OK - Success // HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) - Group Access Check Failed because file ( directory ) doesn't exist // HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) - Group doesn't physically exist ( during CreateFile ) // HRESULT_FROM_WIN32( ERROR_FILE_EXISTS) - The article with the same article id physically exists ( during CreateFile ) // HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED ) - Access Denied // Other - Other fatal errors that might cause UnsafeClose(); // Note: // This also applies to AllocMessage. Since we have no access to IMailMsg // IDL file, it's doc'd here [local] void CommitPost( [in] IUnknown *punkMessage, // IMsg pointer [in] STOREID *pStoreId, [in] STOREID *rgOtherStoreIDs, [in] HANDLE hToken, [in] INntpComplete *pICompletion, [in] BOOL fAnonymous ); /////////////////////////////////////////////////////////////////////////// // ***** article retrieval, delete methods (ARTICLE, BODY, HEAD, etc): /////////////////////////////////////////////////////////////////////////// // Purpose: // Gets an article from the store // Parameters: // pNewsGroup - The INewsGroup where article is posted to // artId - Article ID for this article // StoreId - STOREID for this article // It contains FID/MID for Exchange store, but nothing for FS. // hFile - File handle for the article // Comment: // o FS uses pNewsGroup and artId to retrieve articles, no need for StoreId // o Exchange needs StoreId to give a pair of FID/MID // o If no FID/MID is found, get group properties from pNewsGroup and try // to retrieve article by article number. // o Return an hFile - NEED TO COMEUP WITH AN ASYNC MODEL. // Return value from completion object: // o S_OK - Succeeded // o HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) - Article doesn't exist // o HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) - Group doesn't exist // o E_ACCESSDENIED - Access denied // o OTHER: Fatal server error [local] void GetArticle( [in] INNTPPropertyBag *pPrimaryGroup, [in] INNTPPropertyBag *pCurrentGroup, [in] ARTICLEID PrimaryArtId, [in] ARTICLEID CurrentArtId, [in] STOREID StoreId, [in] HANDLE hToken, [out] void **pvFileHandleContext, [in] INntpComplete *pICompletion, [in] BOOL fAnonymous ); // Purpose: // This is called when the protocol needs to cancel an article // Parameters: // pGroupBag - Group property bag // cArticles - Number of articles to delete // rgidArt - Array of article id's to delete ( used by exdriver ) // rgidStore - Array of store id's to delete ( used by fsdriver ) // hToken - Client's access token // piFailed - To return the index into article array of the first // failed article // pICompletion - Completion object // Return value in completion object: // S_OK - Succeeded // S_FASLE - Succeeded but protocol has asked to delete too many // but the driver can not take them all, see pdwLastSuccess // for the last successfully deleted article // NNTP_E_PARTIAL_COMPLETE - No error, but not all messages are deleted // deletion partly failed in store // Otherwise, Failed [local] void DeleteArticle( [in] INNTPPropertyBag *pGroupBag, [in] DWORD cArticles, [in] ARTICLEID rgidArt[], [in] STOREID rgidStore[], [in] HANDLE hToken, [out] DWORD *pdwLastSuccess, [in] INntpComplete *pICompletion, [in] BOOL fAnonymous ); /////////////////////////////////////////////////////////////////////////// // ***** XOVER, XHDR retrieval methods: /////////////////////////////////////////////////////////////////////////// // Purpose: // Gets the XOVER information for a range of articles // Parameters: // pNewsGroup - The NewsGroup object to get XOVER data from // idMinArticle - the first article to get information for // idMaxArticle - the last article to get information for // idNextArticle - The next article id that you should start from, if you // want // pszHeader - contains a string of header to be retrieved. // ie. "Subject", "From", For Xover, may use "@Xover", where // any string started with "@" is special. // pBuffer - where to put the information (ISSUE: what type is this? // stream or char *) // cbin - size of pBuffer // cbout - total count bytes of returned XOVER data // Return value from completion object: // S_OK - Succeeded perfectly // S_FALSE - Succeeded, but: // 1. If *idNextArticle > idMaxArticle - no article found // 2. If *idNextArticle <= idMaxArticle - Buffer too small, // though some entries have been filled // HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) // - Buffer too small, even first article can not be filled // Other - Other fatal error [local] void GetXover( [in] INNTPPropertyBag *pGroupPropBag, [in] ARTICLEID idMinArticle, [in] ARTICLEID idMaxArticle, [out] ARTICLEID *idNextArticle, [out] CHAR* pBuffer, [in] DWORD cbin, [out] DWORD *cbout, [in] HANDLE hToken, [in] INntpComplete *pICompletion, [in] BOOL fAnonymous ); [local] HRESULT GetXoverCacheDirectory( [in] INNTPPropertyBag* pGroupPropBag, [out] CHAR* pBuffer, [in] DWORD cbIn, [out] DWORD *pcbOut, [out] BOOL* fFlatDir ) ; // Get XHdr information from the driver - similar to GetXover [local] void GetXhdr( [in] INNTPPropertyBag *pGroupPropBag, [in] ARTICLEID idMinArticle, [in] ARTICLEID idMaxArticle, [out] ARTICLEID *idNextArticle, [in] CHAR* pszHeader, [out] CHAR* pBuffer, [in] DWORD cbin, [out] DWORD *cbOut, [in] HANDLE hToken, [in] INntpComplete *pICompletion, [in] BOOL fAnonymous ); /////////////////////////////////////////////////////////////////////////// // ***** Store rebuild related methods: /////////////////////////////////////////////////////////////////////////// // Purpose: // Rebuild a news group: pick up every message, parse out its groups/ // articleid's and use INntpServer's post interface to insert xover/ // article entries. It updates group properties such as article counts, // high/low watermarks too [local] void RebuildGroup( [in] INNTPPropertyBag *pPropBag, [in] HANDLE hToken, [in] INntpComplete *pIComplete ); /////////////////////////////////////////////////////////////////////////// // ***** Newsgroup manipulation methods: /////////////////////////////////////////////////////////////////////////// // Purpose: // Get properties from a group. // Parameters: // pNewsGroup - Property bag for the news group object // cProperties - Number of properties to get // rgidProperties - Array of properties to get [local] void DecorateNewsGroupObject( [in] INNTPPropertyBag *pNewsGroup, [in] DWORD cProperties, [in] DWORD *rgidProperties, [in] INntpComplete *pICompletion ); // Purpose: // Check if client has desired access to this group // Parameters: // pNewsGroup - Property bag to the news group // hToken - The client's access token // dwDesiredAccess - Access rights that the client desires // pICompletion - Pointer to completion object // Return value from completion object: // S_OK - Client has access // E_ACCESSDENIED - Access denied [local] void CheckGroupAccess( [in] INNTPPropertyBag *pNewsGroup, [in] HANDLE hToken, [in] DWORD dwDesiredAccess, [in] INntpComplete *pICompletion ); // Purpose: // Set Newsgroup properties into store // Parameters: // pNewsGroup - The news group property bag // cProperties - Number of properties to set // rgidProperties - Array of properties to set // pICompletion - Completion object // Return values: [local] void SetGroupProperties( [in] INNTPPropertyBag *pNewsGroup, [in] DWORD cProperties, [in] DWORD *rgidProperties, [in] HANDLE hToken, [in] INntpComplete *pICompletion, [in] BOOL fAnonymous ); // Purpose: // Decorate entire INewsTree object by going to the store and get // all the necessary properties. // Parameters: // punkNewsTree - INewsTree to be decorated // hToken - hToken for the user // dwSessionKey - TCP session key // lpvCompletionObj - Completion object in protocol to handle completion // pdwNDS - NNTP driver status [local] void DecorateNewsTreeObject( [in] HANDLE hToken, [in] INntpComplete *pICompletion ); // Purpose: // Create a new group in the store (newgroup) // Parameters: // pszGroupName - the group to create // Comment: // o Lookup virtual root to construct full path name using pszGroupName // o Create the directory structure with full path name [local] void CreateGroup( [in] INNTPPropertyBag* pGroupBag, [in] HANDLE hToken, [in] INntpComplete* pICompletion, [in] BOOL fAnonymous ); // Purpose: // Remove a group from the store (rmgroup). This should include a file // scan operation in the store to delete all articles within the group. // This may be done the same way as MCIS 2.0, when article cleanup is // handled by expiration thread. Groups to be removed is queued up. // Parameters: // pNewsGroup - Newsgroup to be removed. [local] void RemoveGroup( [in] INNTPPropertyBag *pGroupBag, [in] HANDLE hToken, [in] INntpComplete *pICompletion, [in] BOOL fAnonymous ); }; // // Driver interface to establish connection to Exchange store // [ object, uuid(D61569A0-D3F9-11d1-A58C-00C04FA375BA), helpstring("INntpDriverPrepare Interface"), ] interface INntpDriverPrepare : IUnknown { // Purpose: // Initialize driver specific data structure, ie Epoxy connection, etc. // Parameters: // pszVRootPath - virtual root path this driver interface maps to // ie. Nntpsvc/1/root/alt // pLookup - a pointer to the server's ILookup interface // pNewsTree - a pointer to the server's INewsTree interface // pCompletion - a pointer to the server's ICompletion interface // Comments: // o This function is async and returns to the caller without blocking. // o A seperate thread is spawned out to do any blocking operations. [local] void Connect( [in] LPCWSTR pszVRootPath, [in] LPCSTR pszGroupPrefix, [in] IUnknown *punkMetabase, [in] INntpServer* pIServer, [in] INewsTree* pINewsTree, [out] INntpDriver** ppIGoodDriver, [in] INntpComplete* pICompletion, [in] HANDLE hToken, [in] DWORD dwFlag ); // Purpose: // Cancel the pending Connect request // Parameters: // None // Comments: // o Cancel any outstanding connection requests // o Other tasks? [local] HRESULT CancelConnect(); }; [ object, uuid(9E2D8DE8-6926-11d2-9F03-00C04F8EF2F1), helpstring("INntpDriverSearch Interface") ] interface INntpDriverSearch : IUnknown { [local] void MakeSearchQuery ( [in] CHAR *pszSearchString, [in] INNTPPropertyBag *pGroupBag, [in] BOOL bDeepQuery, [in] WCHAR *pwszColumns, [in] WCHAR *pwszSortOrder, [in] LCID LocaleID, [in] DWORD cMaxRows, [in] HANDLE hToken, [in] BOOL fAnonymous, [in] INntpComplete *pICompletion, [out] INntpSearchResults **pINntpSearch, [in] LPVOID lpvContext); [local] void MakeXpatQuery ( [in] CHAR *pszSearchString, [in] INNTPPropertyBag *pGroupBag, [in] BOOL bDeepQuery, [in] WCHAR *pwszColumns, [in] WCHAR *pwszSortOrder, [in] LCID LocaleID, [in] DWORD cMaxRows, [in] HANDLE hToken, [in] BOOL fAnonymous, [in] INntpComplete *pICompletion, [out] INntpSearchResults **pINntpSearch, [out] DWORD *pLowArticleID, [out] DWORD *pHighArticleID, [in] LPVOID lpvContext); [local] BOOL UsesSameSearchDatabase( [in] INntpDriverSearch *pDriver, [in] LPVOID lpvContext ); [local] void GetDriverInfo( [out] GUID *pDriverGUID, [out] void **ppvDriverInfo, [in] LPVOID lpvContext ); }; [ object, uuid(b72a754e-746c-11d2-9f04-00c04f8ef2f1), helpstring("INntpSearch Interface") ] interface INntpSearchResults : IUnknown { [local] void GetResults ( [in,out] DWORD *pcResults, [out] BOOL *pfMore, [out] WCHAR **pGroupName, [out] DWORD *pdwArticleID, [in] INntpComplete *pICompletion, [in] HANDLE hToken, [in] BOOL fAnonymous, [in] LPVOID lpvContext); }; [ uuid(ADD104FE-99C5-11D1-9128-00C04FC30A64), version(1.0), helpstring("inntpdrv 1.0 Type Library") ] library INNTPDRVLib { importlib("stdole2.tlb"); [ uuid(ADD10510-99C5-11D1-9128-00C04FC30A64), helpstring("NntpDriverPrepare Class") ] coclass NntpDriverPrepare { [default] interface INntpDriverPrepare; }; };