In the past, the Windows CE file explorer required every File System Driver (FSD) to perform call-back notifications after every file system change. This notification mechanism allowed file explorer to quickly refresh open views when files were added, deleted, or modified from a directory. Starting with Windows CE version 4.2, this callback mechanism is no longer used by the file explorer. Instead, file explorer uses event-based file notifications (introduced in CE 4.0) which are automatically provided by the Windows CE Storage Manager (FSDMGR.DLL) for every FSD.
However, Windows Mobile platforms (including Windows Mobile 5) still require the older callback style notifications in order to refresh open explorer windows. FSD developers must implement these notification callbacks in order to properly integrate with Windows Mobile platforms. Since documentation on implementing this notification callback system is somewhat lacking, I've put together this brief rundown of the requirements.
Before notifications can be posted by an FSD, the file explorer will register a callback function pointer of the type SHELLFILECHANGEFUNC_t. An FSD will receive a call to FSD_RegisterFileSystemFunction register this callback function pointer. The following example illustrates how an FSD might implement the registration function:
BOOL FSD_RegisterFileSystemFunction (DWORD dwVolume,
SHELLFILECHANGEFUNC_t pNotifyCallBack)
{
// Parameter 1 is always a pointer to our volume structure.
InternalVolumeObject* pVolume = (InternalVolumeObject*)dwVolume;
// Update the volume object's callback function pointer.
pVolume->pNotifyCallBack = pNotifyCallback;
return TRUE;
}
If there is a callback function registered, it should be called from every FSD function after any file change occurs. When calling this function, the FSD must pass a FILECHANGEINFO structure describing the change that occurred. Whenever this structure is populated with a file name, the file name must include the full path to the file, including the name of the mount point. It is recommended that the FSD retrieve the name of the mount point using the FSDMGR_GetVolumeName helper function during the call to FSD_MountDisk after calling FSDMGR_RegisterVolume. The folder name can then be cached in the volume object for later retrieval.
The values used to populate the FILECHANGEINFO structure depend on the file operation that is being processed. The structure contains attributes, modification time, and current file size. For notifications describing items that have been removed, the attributes, modification time, and size fields will be ignored. For notifications describing directories, the modification time and size fields will be ignored.
The following sections explain what each FILECHANGEINFO structure should contain for every file operation. Keep in mind that these notifications should only be posted to the callback function after the operation successfully completes. All definitions can be found in the extfile.h header file.
FSD_CreateFileW
Whenever a new file is created or an existing file is truncated, a notification must be generated. If an existing file is being opened without truncation, no notification should be generated.
A new file is being created:
FILECHANGEINFO.wEventId = SHCNE_CREATE
An existing file is being truncated:
FILECHANGEINFO.wEventId = SHCNE_UPDATEITEM
FILECHANGEINFO.uFlags = SHCNF_PATH | SHCNF_FLUSHNOWAIT
FILECHANGEINFO.dwItem1 = root name + full path to file
FILECHANGEINFO.dwItem2 = 0
FILECHANGEINFO.dwAttributes = current attributes of the new or truncated file
FILECHANGEINFO.ftModified = last modification time this file (now)
FILECHANGEINFO.nFileSize = current file size
FSD_CloseFile
Whenever a file that was opened for write access is closed, the following notification must be generated.
FILECHANGEINFO.wEventId = SHCNE_UPDATEITEM
FILECHANGEINFO.uFlags = SHCNF_PATH | SHCNF_FLUSHNOWAIT
FILECHANGEINFO.dwItem1 = root name + full path to file
FILECHANGEINFO.dwItem2 = 0
FILECHANGEINFO.dwAttributes = current attributes of the new or truncated file
FILECHANGEINFO.ftModified = last modification time this file
FILECHANGEINFO.nFileSize = current file size
FSD_CreateDirectoryW
Whenever a new directory is created, the following notification should be generated.
FILECHANGEINFO.wEventId = SHCNE_MKDIR
FILECHANGEINFO.uFlags = SHCNF_PATH | SHCNF_FLUSHNOWAIT
FILECHANGEINFO.dwItem1 = root name + full path to directory
FILECHANGEINFO.dwItem2 = 0
FILECHANGEINFO.dwAttributes = attributes of the directory (including FILE_ATTRIBUTE_DIRECTORY)
FILECHANGEINFO.ftModified = don’t care
FILECHANGEINFO.nFileSize = don’t care
FSD_RemoveDirectoryW
Whenever a new directory is removed, the following notification should be generated.
FILECHANGEINFO.wEventId = SHCNE_RMDIR
FILECHANGEINFO.uFlags = SHCNF_PATH | SHCNF_FLUSHNOWAIT
FILECHANGEINFO.dwItem1 = root name + full path to directory
FILECHANGEINFO.dwItem2 = 0
FILECHANGEINFO.dwAttributes = don’t care
FILECHANGEINFO.ftModified = don’t care
FILECHANGEINFO.nFileSize = don’t care
FSD_SetFileAttributesW
Whenever the attributes of a file or directory are changed, the following notification should be generated.
FILECHANGEINFO.wEventId = SHCNE_UPDATEITEM
FILECHANGEINFO.uFlags = SHCNF_PATH | SHCNF_FLUSHNOWAIT
FILECHANGEINFO.dwItem1 = root name + full path to file
FILECHANGEINFO.dwItem2 = 0
FILECHANGEINFO.dwAttributes = current attributes of the new or truncated file
FILECHANGEINFO.ftModified = last modification time this file (don’t care for directory)
FILECHANGEINFO.nFileSize = current file size (don’t care for directory)
FSD_DeleteFileW
Whenever a file is deleted, the following notification should be generated.
FILECHANGEINFO.wEventId = SHCNE_DELETE
FILECHANGEINFO.uFlags = SHCNF_PATH | SHCNF_FLUSHNOWAIT
FILECHANGEINFO.dwItem1 = root name + full path to file
FILECHANGEINFO.dwItem2 = 0
FILECHANGEINFO.dwAttributes = don’t care
FILECHANGEINFO.ftModified = don’t care
FILECHANGEINFO.nFileSize = don’t care
FSD_MoveFileW
Whenever a file or directory is moved or renamed, the following notification should be generated.
For MoveFileW on a directory:
FILECHANGEINFO.wEventId = SHCNE_RENAMEFOLDER
For MoveFileW on a file:
FILECHANGEINFO.wEventId = SHCNE_RENAMEITEM
FILECHANGEINFO.uFlags = SHCNF_PATH | SHCNF_FLUSHNOWAIT
FILECHANGEINFO.dwItem1 = root name + full path to old file
FILECHANGEINFO.dwItem2 = root name + full path to new file
FILECHANGEINFO.dwAttributes = don’t care
FILECHANGEINFO.ftModified = don’t care
FILECHANGEINFO.nFileSize = don’t care
The following example illustrates how an FSD would generate a notification for a delete file operation:
BOOL FSD_DeleteFileW (DWORD dwVolume, const WCHAR* pFileName)
{
// Parameter 1 is always a pointer to our volume structure.
InternalVolumeObject* pVolume = (InternalVolumeObject*)dwVolume;
// Perform the internal delete file call to delete the file on
// the volume.
BOOL fResult = InternalDeleteFile (pVolume, pFileName);
if (fResult && pVolume->pNotifyCallBack) {
// Post a file notification on successful file deletion.
// NOTE: This functionality could be offloaded to a helper function
// and invoked by multiple functions posting notifications.
FILECHANGEINFO fci;
WCHAR FullPathName[MAX_PATH];
// Build the full path name using the root folder name + the file name
if (SUCCEEDED (StringCchPrintfW(FullPathName, MAX_PATH, L"%s//%s",
pVolume->RootFolderName, pFileName))) {
fci.wEventId = SHCNE_DELETE;
fci.uFlags = SHCNF_PATH | SHCNF_FLUSHNOWAIT;
fci.dwItem1 = (DWORD)FullPathName;
fci.dwItem2 = 0;
fci.dwAttributes = INVALID_FILE_ATTRIBUTES;
fci.ftModified = 0;
fci.nFileSize = 0;
__try {
// Perform the callback.
(pVolume->pNotifyCallBack) (&fci);
__except (EXCEPTION_EXECUTE_HANDLER) {
// Ignore an exception in the callback.
}
}
}
return fResult;
}
Questions/Comments? Please don't hesitate to send feedback.
-Andrew
Per Lindgaard Andersen
7 Sep 2005 7:31 AM
Hello Andrew !
I am implementing an FSD on a mobile 4.2 device. The FSD is for an ftp client over bluetooth. The notifications does not seem to work, however I am getting a pointer for the function, but if I delete a file in the explore, the delete function is called, but when I try to notify the explore from within the delete function nothing happens.
If you have any suggestions it will be appreciated.
ce_base
7 Sep 2005 4:32 PM
Nothing immediately comes to mind. Do other notifications (besides DeleteFile) work properly? Have you prepended the mount point name to the path of the file being deleted (e.g. "//Storage Card" + "//FileName")?
Per Lindgaard Andersen
8 Sep 2005 8:19 AM
Hi Andrew !
I have also tried with creating a new folder, and I got the same result nothing happens on the file explore, even though I am using the fullpath.
I am sending the notification code for make directory :-)
if(result == TRUE && ptrToRegisterFunc)
{
timeModified.dwLowDateTime = 0; timeModified.dwHighDateTime = 0;
fullPathName = (TCHAR*)malloc(MAX_PATH);
memset((WCHAR*)fullPathName, 0, MAX_PATH);
FSDMGR_GetVolumeName( volumeH, fullPathName, MAX_PATH);
wcscat(fullPathName, pwsPathName);
fci.wEventId = SHCNE_MKDIR;
fci.uFlags = SHCNF_PATH | SHCNF_FLUSHNOWAIT;
fci.dwItem1 = (DWORD) fullPathName;
fci.dwItem2 = 0;
fci.dwAttributes = 0;
fci.ftModified = timeModified;
fci.nFileSize = 0;
IFDBG(DebugOut(DEBUG_OUTPUT, TEXT("[CSR-FSD] Create directory(). Transmitting notification.
FullPathname %s registerfunc %u"), fullPathName, ptrToRegisterFunc));
__try {
(ptrToRegisterFunc) (&fci);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
// Ignore an exception in the callback.
}
free(fullPathName);
}
The pointer value of ptrToRegisterFunc is (F000AB80) so I am getting a pointer for the function. I am using the file explore for a QTek 2020.
I really appreciate your help.
ce_base
8 Sep 2005 7:07 PM
Are you sure that you've built the path properly? I cannot tell from the code if pwsPathName is already prefixed with a "//" or not. If it is not, you'll end up with a malformed path "//storage cardfilename" instead of "//storage card//filename". Do any of the file notifications seem to work correctly?
I'm actually only familiar with the way the shell handles notifications in Windows Mobile 5, so it is possible that the details I've described above aren't 100% correct for older versions (PPC2003 in this case). Try putting the file attributes in your notification structure (and maybe even the file time) and see if it makes a difference. It certainly won't hurt anything.
Another thing to note: you have a potential buffer overrun in your code. You should make sure to malloc a buffer that is (sizeof (TCHAR) * MAX_PATH) bytes (and also make sure malloc doesn't return NULL).
Regards,
Andrew
Per Lindgaard Andersen
12 Sep 2005 3:49 PM
Hi Andrew !!
I can now notify the file explore, and it was the file attribute entry that was wrong.
However I am having trouble updating my path in the file explore, when I enter a new folder, and the FSDMGR calls MyFSD_FindFirst, MyFSD_FindNext etc. it seems that the path gets all wrong. Do you have any idea ?
Thanks and best regards,
Per Andersen
ce_base
13 Sep 2005 1:42 PM
I'm glad to hear you have notifications working. It sounds like the solution, then, was to add the approprite attributes to the notification structure when notifying of a new directory. I will update the blog entry to reflect this.
What do you mean "the path gets all wrong"? FindFirstFile and FindNextFile are used by explorer to determine all of the files in a folder. When you create a new folder, say "Folder1", I'd expect you to to get a call to FindFirstFile with the search string "Folder1/*.*" Is this what you're seeing? If there's nothing in the folder (which there probably isn't because it is a new folder), you should fail FindFirstFile by returning INVALID_HANDLE_VALUE and setting the error code to ERROR_NO_MORE_FILES using the SetLastError API. Note that this search string should not mach the folder itself or you'll get called infinitely.
Regards,
Andrew
分享到:
相关推荐
Source Code for 2009 Supercomputing Paper Implementing Sparse Matrix-Vector Multiplication on Throughput-Oriented Processors
Implementing-a-Database-for-Managing-Access-Control-main.rar
Oracle Manufacturing Implementing Oracle E-Records in Discrete Manufacturing Guide Release 11i
this doc introduces the process of PCIE device hog-plug
sappress_implementing_and_configuring_sap_mii
[Microsoft.SharePoint.2010:Creating.and.Implementing.Real-World.Projects(2012.3)].Jennifer.Mason.文字版
m4.pdf/configuring-selinux-policy-report.pdf/implementing-selinux-as-linux-security-module-report.pdf/The_SELinux_Notebook-4th_Edition.pdf/SEAndroid-NDSS2013.pdf/abs2014_seforandroid_smalley.pdf/...
Implementing Fast Fourier Transform Algorithms of Real Valued Sequences With the TMS320 DSP Platform
TPM 相关技术规范
SAP ME 纯英 1.基于之前的老版本ME15.0,而最新的版本目前应该是15.4; 2.主要是基于离散制造行业,缺少关于流程制造行业的内容
Tensorflow框架用于实现使用忆阻器阵列的DNN 在此代码中,我们为基于逆变器的忆阻神经形态硬件设计了一种改进的培训框架,该框架更加便于研究社区使用。 利用行业标准的TensorFlow工具,我们在以前的Matlab培训范例...
Implementing CIFS - The Common Internet File System,由多个分片 PDF 合成的完整文档,非印刷版。
DevOps is the newest revolution in deploying software quickly and efficiently. With a set of automation tools, an orchestration platform, and a few processes, companies can speed up the release cycle ...
Implementing Domain-Driven Design 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国亚马逊官网搜索此书
implementing-as400-security.tgz
PKI Implementing and Managing E-Security 学习PKI的好书
translation - Implementing-a-Thread-Safe-Queue-using-Condition-Variables实现一个线程安全队列原链接: 翻译: Scott Gu源代码:多线程代码需要一次又一次面对的一个问题是,如何把数据从一个线程传到另一个县城...
calix OLT
05-Implementing Laser Scanned-MEMS Projection in Automotive Head-Up Displays.pdf
DP-100: Designing and Implementing a Data Science Solution on Azure 本次考试的内容于2021年5月20日进行了更新。请下载下面的技能测试文件,看看有何变化。 Azure Data Scientist Associate 认证的考生应具有...