What is the purpose of CopyFileEx's COPY_FILE_OPEN_SOURCE_FOR_WRITE? - winapi

Win32 CopyFileEx and CopyFile2 both have an option flag
COPY_FILE_OPEN_SOURCE_FOR_WRITE where the docs state:
COPY_FILE_OPEN_SOURCE_FOR_WRITE 0x00000004
The file is copied and the original file is opened for write access.
Now, this sounds straightforward, but when I use this flag and try to copy a file that is already opened with "write lock" by someone else, that is no FILE_SHARE_WRITE, but FILE_SHARE_READ, the file is still being copied!
Here is what ProcMon shows when calling this function. Note that these CreateFile events are from a single call to the CopyFileEx function and I omitted the other CreateFile call to the target file:
(sorry for the cinemascope data)
# Without COPY_FILE_OPEN_SOURCE_FOR_WRITE
CreateFile D:\tmp\cpy.txt SUCCESS Desired Access: Generic Read, Disposition: Open, Options: Sequential Access, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened
CreateFile D:\tmp\cpy.txt SUCCESS Desired Access: Generic Read, Disposition: Open, Options: Sequential Access, Synchronous IO Non-Alert, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened
# With COPY_FILE_OPEN_SOURCE_FOR_WRITE
CreateFile D:\tmp\cpy.txt SUCCESS Desired Access: Generic Read/Write, Disposition: Open, Options: Sequential Access, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened
CreateFile D:\tmp\cpy.txt SUCCESS Desired Access: Generic Read/Write, Disposition: Open, Options: Sequential Access, Synchronous IO Non-Alert, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a, OpenResult: Opened
# Without, but file already opened prior by someone else as GENERIC_READ+WRITE + FILE_SHARE_READ (deny write)
CreateFile D:\tmp\cpy.txt SHARING VIOLATION Desired Access: Generic Read, Disposition: Open, Options: Sequential Access, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a
CreateFile D:\tmp\cpy.txt SUCCESS Desired Access: Generic Read, Disposition: Open, Options: Sequential Access, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
CreateFile D:\tmp\cpy.txt SUCCESS Desired Access: Generic Read, Disposition: Open, Options: Sequential Access, Synchronous IO Non-Alert, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
# *With*, but file already opened prior by someone else as GENERIC_READ+WRITE + FILE_SHARE_READ (deny write)
CreateFile D:\tmp\cpy.txt SHARING VIOLATION Desired Access: Generic Read/Write, Disposition: Open, Options: Sequential Access, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a
CreateFile D:\tmp\cpy.txt SHARING VIOLATION Desired Access: Generic Read, Disposition: Open, Options: Sequential Access, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Delete, AllocationSize: n/a
CreateFile D:\tmp\cpy.txt SHARING VIOLATION Desired Access: Generic Read/Write, Disposition: Open, Options: Sequential Access, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
CreateFile D:\tmp\cpy.txt SUCCESS Desired Access: Generic Read, Disposition: Open, Options: Sequential Access, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
CreateFile D:\tmp\cpy.txt SUCCESS Desired Access: Generic Read, Disposition: Open, Options: Sequential Access, Synchronous IO Non-Alert, Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
As we can see, if noone has access to the file before hand, it is indeed opened with Generic Read/Write access.
However, if you look at the non-flag case and especially at the case where someone else already opened the file for writing, I fail to see what this flag actually gains:
Since in both "exclusive" cases, the file is opened with ShareMode: Read, Delete (no share write), noone else can open it for writing anyways in both cases.
In both "shared" cases, if someone else already opened it for writing, the function internally falls back to Desired Access: Generic Read ... ShareMode: Read, Write, Delete anyways.
So,
the flag doesn't prevent anyone from opening the file with read access.
write access is already locked out by ShareMode Read only in the non-flag case
in case it doesn't work, it silently falls back to the non flag case.
So what'the'heck is this flag supposed to achieve? What is the Use Case?

Related

Concatenating mka files but keeping timestamp

I am trying to mix a few files with FFMPEG that are mka and are from a Twilio Video Conference recording. I am trying to get tracks for each participant but I am trying to keep the overall timestamp from the file.
Concrete example: i have these three files:
0PA1896e43f4ca0edf17d8dbfc0bab95a52.mka
1PA2a640f11bc13af2c29397800f058cb05.mka
2PA9fa5b32edc016f6f5b9669bb9b308d97.mka
These files are all tracks of a participant in the call but joined at different times(left the meeting and re-entered, results in a new file).
I want to mix those files in a single file while keeping the timestamp when it was recorded.
FFProbe shows the start of each of this files:
0PA1896e43f4ca0edf17d8dbfc0bab95a52.mka - Duration: 00:00:17.87, start: 1.360000, bitrate: 78 kb/s
1PA2a640f11bc13af2c29397800f058cb05.mka - Duration: 00:00:22.76, start: 22.521000, bitrate: 78 kb/s
2PA9fa5b32edc016f6f5b9669bb9b308d97.mka - Duration: 00:00:20.36, start: 48.944000, bitrate: 78 kb/s
So the first 00:00:17.87 should be silenced, then append the second file from 00:00:22.76 and the third from 48.944000. This would result a single file with all those 3 recording added but with silence when there is nothing, with all the recordings added. Practically, i want a delay at the start.
Imagine i'm adding a 4th recording that starts at minute 2, between recording 3 and 4 would be a gap of silence.
Or imagine a call with 3 participants but the 3rd one would enter only from minute 5. The first 5 minutes should be silenced so I can pass the trascribe api the 3rd participant and still get the correct timestamps.
The reason i want it this way is because I want to transcribe the audio to text and want the exact timestamp when the text can be heard.
You would use the aresample and amix filters for this. The aresample filter will be applied to each input in order to insert silence till the starting timestamp. These processed streams are then mixed together with the amix filter.
I'm going call the inputs 0.mka, 1.mka and 2.mka
ffmpeg -copyts -i 0.mka -i 1.mka -i 2.mka -filter_complex "[0]aresample=async=1:first_pts=0[a0];[1]aresample=async=1:first_pts=0[a1];[2]aresample=async=1:first_pts=0[a2];[a0][a1][a2]amix=inputs=3" out.mka

RTMP server can't stream video (only audio)

I'm implementing an RTMP server right now, and everything's been working except for video streaming. I can stream audio with no problems (using OBS to stream), and play it back via VLC. The problem is VLC plays the audio, but no video. What I'm doing right now is forwarding every audio and video message I receive from OBS, I grab the original payload (audio/video data) and put in a Type 0 Chunk, since I've seen pretty much every implementation do this. I don't know if I'm missing some sort of processing that should be done on the video data.
If I try to playback with ffmpeg (saving the RTMP stream to an flv file), then I get this output:
[NULL # 000001eb053ed440] missing picture in access unit with size 5209
[AVBSFContext # 000001eb053ecbc0] No start code is found.
rtmp://192.168.1.2/app/publish: could not find codec parameters
Input #0, flv, from 'rtmp://192.168.1.2/app/publish':
Duration: N/A, start: 0.000000, bitrate: N/A
Stream #0:0: Data: none
Stream #0:1: Video: h264, none, 1k tbn
Output #0, flv, to 'av.flv':
Output file #0 does not contain any stream
It says missing picture in access unit with size 5209, No start code is found, and could not find codec parameters. What am I missing here? I know I'm forwarding the payload exactly as I've received it in my server, I even did a hash check on the video payload I'm receiving and the one I'm sending and it's exactly the same. Any help would be greatly appreciated.
Fixed by following #szatmary's suggestion: resending the sequence headers to every playback client before sending any audio/video messages.

NTFS + CreateFile: specify stream offset in pathname?

Is it possible to specify stream offset in the pathname when opening a NTFS file data stream via CreateFile?
What about if pathname starts with \\?\?
E.g. abcd.txt::$DATA specifies offset 0 at the unnamed stream*; is it possible to specify a different offset within the pathname**?
*technically, this also means offset equal to stream length in case WriteFile is called with append
**without ever making use of SetFilePointer
There is no syntax that lets you specify a stream offset in the pathname. See MSDN for the supported syntax:
File Streams
You must seek to the desired offset after opening the stream.

Append to golang gob in a file on disk

I'm trying to save gob-encoded data in a file on disk as a simple datastore. However, when I open it next time the gob encoder just ignores whatever data is already in the file, and starts over sending definitions of already sent formats before sending data. Seeing that gob.Encoder takes an io.Writer, rather than an io.ReadWriter, this makes sense. The encoder has no idea what's in the file, because it cannot read from it.
This is, however, quite inefficient. It's also unnecessarily hard to parse, since you have to reset the decoder each time the encoder restarted when writing to the file, since the gob type id's might've changed.
How can I continue to write to the end of a file containing gob data? Do I have to create a new file, moving all data over so the gob encoder knows what types it already sent, or is there a way for me to tell the encoder what types it should know about already, or some other way? I need it to work across software restarts.
It is not possible to reconstruct an Encoder with the state that some other Encoder had when writing a stream of gob values. If you cannot use the original Encoder when appending values, then you have a couple of options:
Move the data over as you suggest.
Use a framing mechanism to store multiple gob streams to the single file. For example, you can prefix each gob stream with the length of that stream.

SuperCollider: load a mono Buffer from a single channel of a multichannel file

Is there any way to load a mono buffer by reading a single channel from an stereo or maybe a multichannel file?
thx!
[asked on behalf of someone else]
Yes: Buffer has a "readChannel" method that does exactly what you ask.
e.g. to load channel 3:
b = Buffer.readChannel(s, pathToAudioFile, channels: [3]);

Resources