| 1 | #pragma once |
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 3 | |
| 4 | |
| 5 | #ifdef __cplusplus |
| 6 | extern "C" { |
| 7 | #endif |
| 8 | |
| 9 | #define ReleaseMon(mh) if (mh) { MonDestroy(mh); } |
| 10 | #define ReleaseNullMon(mh) if (mh) { MonDestroy(mh); mh = NULL; } |
| 11 | |
| 12 | typedef void* MON_HANDLE; |
| 13 | typedef const void* C_MON_HANDLE; |
| 14 | |
| 15 | // Defined in regutil.h |
| 16 | enum REG_KEY_BITNESS; |
| 17 | |
| 18 | extern const int MON_HANDLE_BYTES; |
| 19 | |
| 20 | // Note: callbacks must be implemented in a thread-safe manner. They will be called asynchronously by a MonUtil-spawned thread. |
| 21 | // They must also be written to return as soon as possible - they are called from the waiter thread |
| 22 | typedef void (*PFN_MONGENERAL)( |
| 23 | __in HRESULT hr, |
| 24 | __in_opt LPVOID pvContext |
| 25 | ); |
| 26 | // This callback is not specific to any wait - it will notify client of any drive status changes, such as removable drive insertion / removal |
| 27 | typedef void (*PFN_MONDRIVESTATUS)( |
| 28 | __in WCHAR chDrive, |
| 29 | __in BOOL fArriving, |
| 30 | __in_opt LPVOID pvContext |
| 31 | ); |
| 32 | // Note if these fire with a failed result it means an error has occurred with the wait, and so the wait will stay in the list and be retried. When waits start succeeding again, |
| 33 | // MonUtil will notify of changes, because it may have not noticed changes during the interval for which the wait had failed. This behavior can result in false positive notifications, |
| 34 | // so all consumers of MonUtil should be designed with this in mind. |
| 35 | typedef void (*PFN_MONDIRECTORY)( |
| 36 | __in HRESULT hr, |
| 37 | __in_z LPCWSTR wzPath, |
| 38 | __in BOOL fRecursive, |
| 39 | __in_opt LPVOID pvContext, |
| 40 | __in_opt LPVOID pvDirectoryContext |
| 41 | ); |
| 42 | typedef void (*PFN_MONREGKEY)( |
| 43 | __in HRESULT hr, |
| 44 | __in HKEY hkRoot, |
| 45 | __in_z LPCWSTR wzSubKey, |
| 46 | __in REG_KEY_BITNESS kbKeyBitness, |
| 47 | __in BOOL fRecursive, |
| 48 | __in_opt LPVOID pvContext, |
| 49 | __in_opt LPVOID pvRegKeyContext |
| 50 | ); |
| 51 | |
| 52 | // Silence period allows you to avoid lots of notifications when a lot of writes are going on in a directory |
| 53 | // MonUtil will wait until the directory has been "silent" for at least dwSilencePeriodInMs milliseconds |
| 54 | // The drawback to setting this to a value higher than zero is that even single write notifications |
| 55 | // are delayed by this amount |
| 56 | HRESULT DAPI MonCreate( |
| 57 | __out_bcount(MON_HANDLE_BYTES) MON_HANDLE *pHandle, |
| 58 | __in PFN_MONGENERAL vpfMonGeneral, |
| 59 | __in_opt PFN_MONDRIVESTATUS vpfMonDriveStatus, |
| 60 | __in_opt PFN_MONDIRECTORY vpfMonDirectory, |
| 61 | __in_opt PFN_MONREGKEY vpfMonRegKey, |
| 62 | __in_opt LPVOID pvContext |
| 63 | ); |
| 64 | // Don't add multiple identical waits! Not only is it wasteful and will cause multiple fires for the exact same change, it will also |
| 65 | // result in slightly odd behavior when you remove a duplicated wait (removing a wait may or may not remove multiple waits) |
| 66 | // This is due to the way coordinator thread and waiter threads handle removing, and while it is possible to solve, doing so would complicate the code. |
| 67 | // So instead, de-dupe your wait requests before sending them to MonUtil. |
| 68 | // Special notes for network waits: MonUtil can send false positive notifications (i.e. notifications when nothing had changed) if connection |
| 69 | // to the share is lost and reconnected, because MonUtil can't know for sure whether changes occurred while the connection was lost. |
| 70 | // Also, MonUtil will very every 20 minutes retry even successful network waits, because the underlying Win32 API cannot notify us if a remote server |
| 71 | // had its network cable unplugged or similar sudden failure. When we retry the successful network waits, we will also send a false positive notification, |
| 72 | // because it's impossible for MonUtil to detect if we're reconnecting to a server that had died and come back to life, or if we're reconnecting to a server that had |
| 73 | // been up all along. For both of the above reasons, clients of MonUtil must be written to do very, very little work in the case of false positive network waits. |
| 74 | HRESULT DAPI MonAddDirectory( |
| 75 | __in_bcount(MON_HANDLE_BYTES) MON_HANDLE handle, |
| 76 | __in_z LPCWSTR wzPath, |
| 77 | __in BOOL fRecursive, |
| 78 | __in DWORD dwSilencePeriodInMs, |
| 79 | __in_opt LPVOID pvDirectoryContext |
| 80 | ); |
| 81 | HRESULT DAPI MonAddRegKey( |
| 82 | __in_bcount(MON_HANDLE_BYTES) MON_HANDLE handle, |
| 83 | __in HKEY hkRoot, |
| 84 | __in_z LPCWSTR wzSubKey, |
| 85 | __in REG_KEY_BITNESS kbKeyBitness, |
| 86 | __in BOOL fRecursive, |
| 87 | __in DWORD dwSilencePeriodInMs, |
| 88 | __in_opt LPVOID pvRegKeyContext |
| 89 | ); |
| 90 | HRESULT DAPI MonRemoveDirectory( |
| 91 | __in_bcount(MON_HANDLE_BYTES) MON_HANDLE handle, |
| 92 | __in_z LPCWSTR wzPath, |
| 93 | __in BOOL fRecursive |
| 94 | ); |
| 95 | HRESULT DAPI MonRemoveRegKey( |
| 96 | __in_bcount(MON_HANDLE_BYTES) MON_HANDLE handle, |
| 97 | __in HKEY hkRoot, |
| 98 | __in_z LPCWSTR wzSubKey, |
| 99 | __in REG_KEY_BITNESS kbKeyBitness, |
| 100 | __in BOOL fRecursive |
| 101 | ); |
| 102 | void DAPI MonDestroy( |
| 103 | __in_bcount(MON_HANDLE_BYTES) MON_HANDLE handle |
| 104 | ); |
| 105 | |
| 106 | #ifdef __cplusplus |
| 107 | } |
| 108 | #endif |