#include <os/filesys.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include "folder.h" #if 0 #define TRACE wprintf #else static int TRACE(...) { return 0; } #endif extern "C" bool wildcard(const wchar_t* str, const wchar_t* spec); extern "C" IFolder* Folder_Create() { return new CFolder; } CFolder::CFolder() { m_refs = 0; m_item_first = NULL; m_scanned = false; } CFolder::~CFolder() { folderitem_ext_t *item, *next; for (item = m_item_first; item; item = next) { next = item->next; if (item->mount) item->mount->Release(); //IUnknown_Release(item->mount); item->mount = NULL; free(item->name); delete item; } } HRESULT CFolder::QueryInterface(REFIID iid, void ** ppvObject) { if (InlineIsEqualGUID(iid, IID_IUnknown) || InlineIsEqualGUID(iid, IID_IFolder)) { AddRef(); *ppvObject = (IFolder*) this; return S_OK; } else return E_FAIL; } HRESULT CFolder::FindFirst(const wchar_t* szSpec, folderitem_t* item) { if (!m_scanned) { ScanDir(); m_scanned = true; } item->spec = wcsdup(szSpec); item->u.find_handle = (dword) m_item_first; return S_OK; } HRESULT CFolder::FindNext(folderitem_t* item) { folderitem_ext_t *fitem = (folderitem_ext_t*) item->u.find_handle; if (fitem == NULL) return E_FAIL; else { while (fitem) { if (wildcard(fitem->name, item->spec)) { item->u.find_handle = (dword) fitem->next; wcsncpy(item->name, fitem->name, item->name_max); item->attributes = fitem->attributes; item->length = fitem->length; if (item->size == sizeof(folderitem_ext_t)) { ((folderitem_ext_t*) item)->next = fitem->next; ((folderitem_ext_t*) item)->mount = fitem->mount; ((folderitem_ext_t*) item)->data = fitem->data; } return S_OK; } fitem = fitem->next; item->u.find_handle = (dword) fitem; } return E_FAIL; } } HRESULT CFolder::FindClose(folderitem_t* pBuf) { free((void*) pBuf->spec); return S_OK; } HRESULT CFolder::Open(folderitem_t* item, const wchar_t* params) { folderitem_ext_t buf; IUnknown* pFile; wchar_t temp[MAX_PATH]; TRACE(L"[OpenChild] %s\n", item->name); memset(&buf, 0, sizeof(buf)); buf.size = sizeof(buf); buf.name = temp; buf.name_max = countof(temp); if (FAILED(FindFirst(item->name, &buf)) || FAILED(FindNext(&buf))) return E_FAIL; pFile = DoOpen(&buf); if (item->size == sizeof(folderitem_ext_t)) memcpy(item, &buf, sizeof(folderitem_ext_t)); else *item = buf; item->u.item_handle = pFile; FindClose(&buf); return S_OK; } HRESULT CFolder::Mount(const wchar_t* name, IUnknown* obj) { folderitem_ext_t* item; folderitem_t info; //IStream* strm; TRACE(L"CFolder::Mount(%s, %p)\n", name, obj); for (item = m_item_first; item; item = item->next) { if (wcsicmp(name, item->name) == 0) { if (item->mount) item->mount->Release(); break; } } if (item == NULL) { item = new folderitem_ext_t; memset(item, 0, sizeof(item)); item->next = m_item_first; m_item_first = item; item->name = wcsdup(name); } info.size = sizeof(info); info.name = NULL; info.name_max = 0; info.attributes = 0; info.length = 0; /*if (obj && SUCCEEDED(obj->QueryInterface(IID_IStream, (void**) &strm))) { strm->Stat(&info); strm->Release(); }*/ item->size = sizeof(folderitem_ext_t); item->attributes = ATTR_LINK | info.attributes; item->length = info.length; item->mount = obj; obj->AddRef(); return S_OK; } void CFolder::ScanDir() { } IUnknown* CFolder::DoOpen(folderitem_ext_t* buf) { if (buf->mount) { buf->mount->AddRef(); return buf->mount; } else return NULL; }