NetWrite.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:23k
- unit NetWrite;
- interface
- uses Windows, wmf9, SysUtils, activex, Classes;
- const
- NETWRITE_ASYNC_EVENT : PCHAR = '{6d12fe9b-d029-4d08-b2eb-92c8cab323c7}';
- type
- TWMFNetWrite = class(TObject, IWMReaderCallback, IWMReaderCallbackAdvanced)
- public
- constructor Create;
- destructor Destroy; override;
- function Configure(dwPortNum: DWORD; const pwszFile: PWideChar; nMaxClient: cardinal): HRESULT;
- function WritetoNet: HRESULT;
- function Init: HRESULT;
- //Methods of IWMReaderCallback
- function OnSample(dwOutputNum: DWORD; cnsSampleTime, cnsSampleDuration: int64;
- dwFlags: DWORD; pSample: INSSBuffer; pvContext: pointer): HRESULT; stdcall;
- function OnStatus(Status: TWMTSTATUS; hr: HRESULT; dwType: TWMTATTRDATATYPE;
- pValue: PBYTE; pvContext: pointer): HRESULT; stdcall;
- //Methhods of IWMReaderCallbackAdvanced
- // Receive a sample directly from the ASF. To get this call, the user
- // must register himself to receive samples for a particular stream.
- function OnStreamSample(wStreamNum: WORD; cnsSampleTime, cnsSampleDuration: int64;
- dwFlags: DWORD; pSample: INSSBuffer; pvContext: pointer): HRESULT; stdcall;
- // In some cases, the user may want to get callbacks telling what the
- // reader thinks the current time is. This is interesting in 2 cases:
- // - If the ASF has gaps in it; say no audio for 10 seconds. This call
- // will continue to be called, while OnSample won't be called.
- // - If the user is driving the clock, the reader needs to communicate
- // back to the user its time, to avoid the user overrunning the reader.
- function OnTime(cnsCurrentTime: int64; pvContext: pointer): HRESULT; stdcall;
- // The user can also get callbacks when stream selection occurs.
- function OnStreamSelection(wStreamCount: Word; pStreamNumbers: PWord;
- pSelections: PWMTSTREAMSELECTION; pvContext: Pointer): HResult; stdcall;
- // Will be called if the user got an async result from their
- // call to SetOutputProps. The next sample you receive for
- // this output will have these properties. The contents of the
- // media type after calling SetOutputProps and before receiving
- // an OutputPropsChanged notification are undefined.
- function OnOutputPropsChanged(dwOutputNum: DWORD; pMediaType: PWMMediaType;
- pvContext: pointer): HRESULT; stdcall;
- // If the user has registered to allocate buffers, this is where he must
- // do it.
- function AllocateForStream(wStreamNum: WORD; cbBuffer: DWORD; out ppBuffer: INSSBuffer;
- pvContext: pointer): HRESULT; stdcall;
- function AllocateForOutput(dwOutputNum, cbBuffer: DWORD; out ppBuffer: INSSBuffer;
- pvContext: pointer): HRESULT; stdcall;
- function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
- function _AddRef: Integer; stdcall;
- function _Release: Integer; stdcall;
- private
- function WriteHeader (const pwszName: PWideChar): HRESULT;
- function WriteScript: HRESULT;
- private
- m_hEvent : THANDLE;
- m_hrAsync : HRESULT;
- m_qwTime : Int64;
- m_pWriterAdvanced : IWMWriterAdvanced;
- m_pReaderAdvanced : IWMReaderAdvanced;
- m_pReader : IWMReader;
- m_pWriter : IWMWriter;
- m_pNetSink : IWMWriterNetworkSink;
- m_bEOF : bool;
- m_pReaderHeaderInfo : IWMHeaderInfo;
- m_pWriterHeaderInfo : IWMHeaderInfo;
- public
- function CloseAll: HRESULT;
- end;
- implementation
- constructor TWMFNetWrite.Create;
- begin
- m_pReaderHeaderInfo := nil;
- m_pWriterHeaderInfo := nil;
- m_pWriterAdvanced := nil;
- m_pReaderAdvanced := nil;
- m_pReader := nil;
- m_pWriter := nil;
- m_pNetSink := nil;
- m_hEvent := 0;
- m_bEOF := false;
- m_qwTime := 0;
- m_hrAsync := S_OK;
- end;
- destructor TWMFNetWrite.Destroy;
- begin
- CloseAll;
- CloseHandle(m_hEvent);
- m_pWriterAdvanced := nil;
- m_pWriter := nil;
- m_pNetSink := nil;
- m_pReaderAdvanced := nil;
- m_pReader := nil;
- inherited destroy;
- end;
- function TWMFNetWrite.Configure(dwPortNum: DWORD; const pwszFile: PWideChar; nMaxClient: cardinal): HRESULT;
- var
- pProfile : IWMProfile;
- pStream : IWMStreamConfig;
- err, cchURL, dwStreams, i, cInputs : DWORD;
- pwszURL : PWideChar;
- wStreamNumber: WORD;
- begin
- if((dwPortNum = 0) or (pwszFile = nil)) then
- begin
- result := E_INVALIDARG;
- exit;
- end;
- if ((m_pWriterAdvanced = nil) or (m_pReaderAdvanced = nil) or (m_pNetSink = nil)) then
- begin
- result := E_UNEXPECTED;
- exit;
- end;
- // Create event for handling asynchronous calls
- result := S_OK;
- pProfile := nil;
- pStream := nil;
- m_hrAsync := S_OK;
- m_hEvent := CreateEvent(nil, FALSE, FALSE, NETWRITE_ASYNC_EVENT);
- if (m_hEvent = 0) then
- begin
- err := GetLastError;
- writeln(format('Could not Create Event: (hr=$%x)',[err]));
- result := err;
- exit;
- end;
- // Configure the Net Sink
- result := m_pNetSink.SetNetworkProtocol(WMT_PROTOCOL_HTTP);
- if (FAILED(result)) then
- begin
- writeln('Could not Set Network protocol');
- exit;
- end;
- result := m_pNetSink.Open(dwPortNum);
- if (FAILED(result)) then
- begin
- writeln(format('Network sink failed to open port no %d',[dwPortNum]));
- exit;
- end;
- cchURL := 0;
- result := m_pNetSink.GetHostURL(nil, cchURL);
- if(FAILED(result)) then
- begin
- writeln('Could not get the host URL from IWMWriterNEtworkSink');
- exit;
- end;
-
- getmem(pwszURL, cchURL * sizeof(WCHAR));
- if (pwszURL = nil) then
- begin
- result := E_OUTOFMEMORY; // Insufficient Memory
- exit;
- end;
- result := m_pNetSink.GetHostURL(pwszURL, cchURL);
- if (FAILED(result)) then
- begin
- writeln('Could not get the host URL from IWMWriterNEtworkSink');
- FreeMem(pwszURL);
- exit;
- end;
- writeln('Connect to '+pwszURL);
- // Sleep(1000);
- FreeMem(pwszURL);
- // Set the max no of clients that can connect to the port
- result := m_pNetSink.SetMaximumClients(nMaxClient);
- if (FAILED(result)) then
- begin
- writeln('Could not Set maximum clients');
- exit;
- end;
- // Add the network sink to the Writer Advanced
- result := m_pWriterAdvanced.AddSink(m_pNetSink);
- if (FAILED(result)) then
- begin
- writeln('Could not Add Sink');
- exit;
- end;
- // Open the requested file
- result := m_pReader.Open(pwszFile, self, nil);
- if (FAILED(result)) then
- begin
- writeln('Could not open file');
- exit;
- end;
- // Wait for the open to finish
- WaitForSingleObject(m_hEvent, INFINITE);
- if (FAILED(m_hrAsync)) then
- begin
- writeln(format('Open failed (hr=$%x)',[m_hrAsync]));
- result := m_hrAsync;
- exit;
- end;
- // Turn on manual stream selection, so we get all streams.
- result := m_pReaderAdvanced.SetManualStreamSelection(TRUE);
- if (FAILED(result)) then
- begin
- writeln('Failed to set manual stream selection');
- exit;
- end; //
- // Get the profile interface, loop thru all the
- // streams and request the reader to deliver compressed samples
- result := m_pReader.QueryInterface(IID_IWMProfile, pProfile);
- if (FAILED(result)) then
- begin
- writeln('Could not Query for IWMProfile');
- exit;
- end;
- dwStreams := 0;
- result := pProfile.GetStreamCount(dwStreams);
- if (FAILED(result)) then
- begin
- writeln(format('GetStreamCount on IWMProfile failed (hr=$%x)', [result]));
- exit;
- end;
- for i := 0 to dwStreams - 1 do
- begin
- result := pProfile.GetStream(i, pStream);
- if (FAILED(result)) then
- begin
- writeln(format('Could not get Stream %d of %d from IWMProfile (hr=0x%08x)',[i,dwStreams,result]));
- break;
- end;
- wStreamNumber := 0;
- //Get the stream number of the current stream
- result := pStream.GetStreamNumber(wStreamNumber);
- if (FAILED(result)) then
- begin
- writeln(format('Could not get stream number from IWMStreamConfig %d of %d (hr=$%x)',
- [i, dwStreams, result]));
- break;
- end;
- pStream := nil;
- //Set the stream to be recieved in compressed mode
- result := m_pReaderAdvanced.SetReceiveStreamSamples(wStreamNumber, TRUE);
- if (FAILED(result)) then
- begin
- writeln(format('Could not SetReceivedStreamSamples for stream number %d (hr=$%x)',
- [wStreamNumber, result]));
- break;
- end;
- end;
- pStream := nil;
- if (FAILED(result)) then exit;
- // Turn on the user clock
- result := m_pReaderAdvanced.SetUserProvidedClock(TRUE);
- if (FAILED(result)) then
- begin
- writeln(format('SetUserProvidedClock failed (hr=$%x)', [result]));
- exit;
- end;
- // Now set the writers properties
- result := m_pWriter.SetProfile(pProfile);
- if(FAILED(result)) then
- begin
- writeln(format('Could not set profile on IWMWriter (hr=$%x)',[result]));
- exit;
- end;
- pProfile := nil;
- cInputs := 0;
- result := m_pWriter.GetInputCount(cInputs);
- if(FAILED(result)) then
- begin
- writeln(format('Could not get input count from IWMWriter (hr=$%x)',[result]));
- exit;
- end;
- for i := 0 to cInputs -1 do
- // Set the input props to NULL to indicate that we don't need a codec
- // because we are writing compressed samples to the port
- m_pWriter.SetInputProps(i, nil);
- // Write all the header attributes, which can be set, from the
- // input file to the output port.
- result := WriteHeader(g_wszWMTitle);
- if(FAILED(result)) then exit;
- result := WriteHeader( g_wszWMAuthor) ;
- if(FAILED(result)) then exit;
- result := WriteHeader( g_wszWMDescription) ;
- if(FAILED(result)) then exit;
- result := WriteHeader( g_wszWMRating) ;
- if(FAILED(result)) then exit;
- result := WriteHeader( g_wszWMCopyright) ;
- if(FAILED(result)) then exit;
- result := WriteHeader( g_wszWMAlbumTitle) ;
- if(FAILED(result)) then exit;
- result := WriteHeader( g_wszWMTrack) ;
- if(FAILED(result)) then exit;
- result := WriteHeader( g_wszWMPromotionURL) ;
- if(FAILED(result)) then exit;
- result := WriteHeader( g_wszWMAlbumCoverURL) ;
- if(FAILED(result)) then exit;
- result := WriteHeader( g_wszWMGenre) ;
- if(FAILED(result)) then exit;
- result := WriteHeader( g_wszWMYear) ;
- if(FAILED(result)) then exit;
- result := WriteHeader( g_wszWMGenreID) ;
- if(FAILED(result)) then exit;
- result := WriteHeader( g_wszWMMCDI) ;
- if(FAILED(result)) then exit;
- result := WriteHeader( g_wszWMBannerImageType ) ;
- if(FAILED(result)) then exit;
- result := WriteHeader( g_wszWMBannerImageData ) ;
- if(FAILED(result)) then exit;
- result := WriteHeader( g_wszWMBannerImageURL ) ;
- if(FAILED(result)) then exit;
- result := WriteHeader( g_wszWMCopyrightURL ) ;
- if(FAILED(result)) then exit;
- //Header has been written. Lets write the script
- result := WriteScript;
- end;
- function TWMFNetWrite.WritetoNet: HRESULT;
- begin
- if ((m_hEvent = 0) or
- (m_pWriterAdvanced = nil) or
- (m_pReaderAdvanced = nil) or
- (m_pNetSink = nil)) then
- begin
- result := E_UNEXPECTED;
- exit;
- end;
- // Start Writing
- result := m_pWriter.BeginWriting;
- if (FAILED(result)) then
- begin
- writeln(format('BeginWriting on IWMWriter failed (hr=$%x)',[result]));
- exit;
- end;
- result := m_pReader.Start(0, 0, 1.0, nil);
- if (FAILED(result)) then
- begin
- writeln(format('Could not start IWMReader (hr=$%x)',[result]));
- exit;
- end;
- // not usefull with Windowed app
- { // Wait for it to finish
- WaitForSingleObject(m_hEvent, INFINITE);
- if (FAILED(m_hrAsync)) then
- begin
- result := m_hrAsync;
- exit; // Net writing failed ????? not logic for hresult
- end;}
- end;
- function TWMFNetWrite.CloseAll: HRESULT;
- begin
- // Stop stuff
- if assigned(m_pReader) then
- begin
- result := m_pReader.Stop;
- if (FAILED(result)) then
- begin
- writeln(format('Could not Stop IWMReader (hr=$%x)',[result]));
- exit;
- end; // Could not Stop IWMReader
- end;
- if assigned(m_pWriter) then
- begin
- result := m_pWriter.Flush;
- if (FAILED(result)) then
- begin
- writeln(format('Could not Flush on IWMWriter (hr=$%x)',[result]));
- exit;
- end;
- result := m_pWriter.EndWriting;
- if (FAILED(result)) then
- begin
- writeln(format('Could not EndWriting on IWMWriter (hr=$%x)',[result]));
- exit;
- end;
- end;
- if assigned(m_pReader) then
- begin
- result := m_pReader.Close;
- if (FAILED(result)) then
- begin
- writeln(format('Could not close the file (hr=$%x)',[result]));
- exit;
- end;
- end;
- if assigned(m_pWriterAdvanced) then
- begin
- result := m_pWriterAdvanced.RemoveSink(m_pNetSink);
- if (FAILED(result)) then
- begin
- writeln(format('Could not remove the Network Sink (hr=$%x)',[result]));
- exit;
- end;
- end;
- if assigned(m_pNetSink) then
- begin
- result := m_pNetSink.Close;
- if (FAILED(result)) then
- begin
- writeln(format('Could not close on IWMWriterNetworkSink (hr=$%x)',[result]));
- exit;
- end;
- end;
- result := s_ok;
- //Wait for sometime till all the data gets read from the port
- //Sleep(20000);
- end;
- function TWMFNetWrite.Init: HRESULT;
- begin
- // Create the reader, writer and network sink.
- result := WMCreateReader( nil, 0, m_pReader);
- if (FAILED(result)) then
- begin
- writeln(format('Could not create reader (hr=$%x)',[result]));
- exit;
- end;
- result := m_pReader.QueryInterface(IID_IWMReaderAdvanced, m_pReaderAdvanced);
- if (FAILED(result)) then
- begin
- writeln(format('Could not QI for IWMReaderAdvanced (hr=$%x)',[result]));
- exit;
- end;
- result := WMCreateWriter(nil, m_pWriter);
- if (FAILED(result)) then
- begin
- writeln(format('Could not create Writer (hr=$%x)',[result]));
- exit;
- end;
- result := m_pWriter.QueryInterface(IID_IWMWriterAdvanced, m_pWriterAdvanced);
- if (FAILED(result)) then
- begin
- writeln(format('Could not QI for IWMWriterAdvanced (hr=$%x)',[result]));
- exit;
- end;
- result := WMCreateWriterNetworkSink(m_pNetSink);
- if (FAILED(result)) then
- begin
- writeln(format('Could not create Writer Network Sink (hr=$%x)',[result]));
- exit;
- end;
- result := m_pReader.QueryInterface(IID_IWMHeaderInfo, m_pReaderHeaderInfo);
- if (FAILED(result)) then
- begin
- writeln(format('Could not QI for IWMHeaderInfo (hr=$%x)',[result]));
- exit;
- end;
- result := m_pWriter.QueryInterface(IID_IWMHeaderInfo, m_pWriterHeaderInfo);
- if (FAILED(result)) then
- begin
- writeln(format('Could not QI for IWMHeaderInfo (hr=$%x)',[result]));
- exit;
- end;
- end;
- function TWMFNetWrite.OnSample(dwOutputNum: DWORD; cnsSampleTime, cnsSampleDuration: int64;
- dwFlags: DWORD; pSample: INSSBuffer; pvContext: pointer): HRESULT;
- begin
- if (m_hEvent <> 0) then
- begin
- //The samples are expected in OnStreamSample
- writeln('Error: Received a decompressed sample from the reader');
- m_hrAsync := E_UNEXPECTED;
- SetEvent(m_hEvent);
- end;
- result := S_OK;
- end;
- function TWMFNetWrite.OnStatus(Status: TWMTSTATUS; hr: HRESULT; dwType: TWMTATTRDATATYPE;
- pValue: PBYTE; pvContext: pointer): HRESULT;
- begin
- case Status of
- WMT_OPENED:
- begin
- m_hrAsync := hr;
- SetEvent(m_hEvent);
- end;
- WMT_END_OF_FILE:
- begin
- m_bEOF := true;
- writeln('EndOfStream detected in reader');
- m_hrAsync := hr;
- SetEvent(m_hEvent);
- end;
- WMT_STARTED:
- begin
- //Ask for the specific duration of the stream to be delivered
- m_qwTime := 0;
- m_qwTime := m_qwTime + (1000 * 10000);
- hr := m_pReaderAdvanced.DeliverTime(m_qwTime);
- assert(SUCCEEDED(hr));
- end;
- end;
- result := S_OK;
- end;
- function TWMFNetWrite.OnStreamSample(wStreamNum: WORD; cnsSampleTime, cnsSampleDuration: int64;
- dwFlags: DWORD; pSample: INSSBuffer; pvContext: pointer): HRESULT;
- begin
- writeln(format('StreamSample: num=%d, time=%d, duration=%d, flags=%d',
- [wStreamNum, cnsSampleTime, cnsSampleDuration, dwFlags]));
- //We've got a sample. Lets write it
- m_pWriterAdvanced.WriteStreamSample( wStreamNum, cnsSampleTime, 0, cnsSampleDuration, dwFlags, pSample);
- result := S_OK;
- end;
- function TWMFNetWrite.OnTime(cnsCurrentTime: int64; pvContext: pointer): HRESULT;
- begin
- //Keep asking for the specific duration of the stream till EOF
- if( not m_bEOF) then
- begin
- m_qwTime := m_qwTime + 10000000;
- m_pReaderAdvanced.DeliverTime(m_qwTime);
- end;
- result := S_OK;
- end;
- function TWMFNetWrite.OnStreamSelection( wStreamCount: Word; pStreamNumbers: PWORD;
- pSelections: PWMTSTREAMSELECTION; pvContext: pointer): HRESULT;
- begin
- result := S_OK;
- end;
- function TWMFNetWrite.OnOutputPropsChanged(dwOutputNum: DWORD; pMediaType: PWMMEDIATYPE;
- pvContext: pointer): HRESULT;
- begin
- result := S_OK;
- end;
- function TWMFNetWrite.AllocateForStream(wStreamNum: WORD; cbBuffer: DWORD; out ppBuffer: INSSBuffer;
- pvContext: pointer): HRESULT;
- begin
- result := E_NOTIMPL;
- end;
- function TWMFNetWrite.AllocateForOutput(dwOutputNum, cbBuffer: DWORD; out ppBuffer: INSSBuffer;
- pvContext: pointer): HRESULT;
- begin
- result := E_NOTIMPL;
- end;
- function TWMFNetWrite.WriteHeader (const pwszName: PWideChar): HRESULT;
- var
- nstreamNum : WORD;
- cbLength : WORD;
- _type : TWMTAttrDataType;
- hr : HRESULT;
- pValue : PBYTE;
- begin
- nstreamNum := 0;
- cbLength := 0;
- result := S_OK;
- pValue := nil;
- // Get the no of bytes to be allocated for pValue
- result := m_pReaderHeaderInfo.GetAttributeByName(nstreamNum, pwszName, _type, nil, cbLength);
- if (FAILED(result) and (result <> longint(ASF_E_NOTFOUND))) then
- begin
- writeln(format('GetAttributeByName failed for Attribute name %s (hr=$%x)',[pwszName, result]));
- exit;
- end;
- if ((cbLength = 0) or (result = longint(ASF_E_NOTFOUND))) then
- begin
- result := S_OK;
- exit;
- end;
- getmem(pValue, cbLength);
- if (pValue = nil) then
- begin
- writeln(format('Unable to allocate memory for the Attribute name %s', [pwszName]));
- result := E_OUTOFMEMORY;
- exit;
- end;
- //Dummy do-while loop
- repeat
- // Get the value
- hr := m_pReaderHeaderInfo.GetAttributeByName(nstreamNum, pwszName, _type, pValue, cbLength);
- if (FAILED(hr)) then
- begin
- writeln(format('GetAttributeByName failed for Attribute name %s (hr=$%x)', [pwszName, hr]));
- break;
- end;
- // Set the attribute
- hr := m_pWriterHeaderInfo.SetAttribute(nstreamNum, pwszName, _type, pValue, cbLength);
- if (FAILED(hr)) then
- begin
- writeln(format('SetAttribute failed for Attribute name %s (hr=$%x)',[pwszName, hr]));
- break;
- end;
- until (FALSE);
- freemem(pValue);
- pValue := nil;
- result := hr;
- end;
- function TWMFNetWrite.WriteScript: HRESULT;
- var
- hr : HRESULT;
- pwszCommand : PWideChar;
- pwszType : PWideChar;
- cnsScriptTime : int64;
- cScript : WORD;
- cchTypeLen : WORD;
- cchCommandLen : WORD;
- i : integer;
- begin
- hr := S_OK;
- pwszCommand := nil;
- pwszType := nil;
- cnsScriptTime := 0;
- cScript := 0;
- cchTypeLen := 0;
- cchCommandLen := 0;
- result := m_pReaderHeaderInfo.GetScriptCount(cScript);
- if (FAILED(result)) then
- begin
- writeln(format('GetScriptCount failed (hr=$%x)',[result]));
- exit;
- end;
- for i := 0 to cScript - 1 do
- begin
- // Get the memory reqd for this script
- hr := m_pReaderHeaderInfo.GetScript(i, nil, cchTypeLen, nil, cchCommandLen, cnsScriptTime);
- if (FAILED(hr)) then
- begin
- writeln(format('GetScript failed for Script no %d (hr=$%x)',[i, hr]));
- break;
- end;
- getmem(pwszType, cchTypeLen * sizeof(WORD));
- getmem(pwszCommand, cchCommandLen * sizeof(WORD));
- if ((pwszType = nil) or (pwszCommand = nil)) then
- begin
- hr := E_OUTOFMEMORY;
- break;
- end;
- // Now, get the script
- hr := m_pReaderHeaderInfo.GetScript(i, pwszType, cchTypeLen, pwszCommand, cchCommandLen, cnsScriptTime);
- if (FAILED(hr)) then
- begin
- writeln(format('GetScript failed for Script no %d (hr=$%x)', [i, hr]));
- break;
- end; // GetScript failed for Script no %d
- // Add the script to the writer
- hr := m_pWriterHeaderInfo.AddScript(pwszType, pwszCommand, cnsScriptTime);
- if (FAILED(hr)) then
- begin
- Writeln(format('AddScript failed for Script no %d (hr=$%x)', [i, hr]));
- break;
- end;
- if pwszType <> nil then freemem(pwszType);
- if pwszCommand <> nil then freemem(pwszCommand);
- pwszType := nil;
- pwszCommand := nil;
- cchTypeLen := 0 ;
- cchCommandLen := 0 ;
- end;
- if pwszType <> nil then freemem(pwszType);
- if pwszCommand <> nil then freemem(pwszCommand);
- pwszType := nil;
- pwszCommand := nil;
- result := hr;
- end;
- function TWMFNetWrite.QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
- begin
- if IsEqualGUID(IID, IID_IWMReaderCallback) then
- IWMReaderCallback(Obj) := self
- else
- if IsEQualGUID(IID, IID_IWMReaderCallbackAdvanced) then
- IWMReaderCallbackAdvanced(obj) := self
- else
- begin
- result := E_NOINTERFACE;
- exit;
- end;
- result := S_OK;
- end;
- function TWMFNetWrite._AddRef: Integer; stdcall;
- begin
- result := 1;
- end;
- function TWMFNetWrite._Release: Integer; stdcall;
- begin
- result := 1;
- end;
- end.