Skip to content

Commit

Permalink
Added more shell interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
evrhel committed May 8, 2024
1 parent 1e9b500 commit 83d4efc
Show file tree
Hide file tree
Showing 4 changed files with 576 additions and 250 deletions.
14 changes: 14 additions & 0 deletions include/lysys/ls_shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ char *ls_strdir(const char *path);
//! NULL if the path separator is not found
char *ls_strrdir(const char *path);

void ls_path_win32(char *path);

void ls_path_unix(char *path);

void ls_path_native(char *path);

//! \brief Get the directory name of a path.
//!
//! Extracts the directory name from a path. The directory name is the
Expand Down Expand Up @@ -106,4 +112,12 @@ size_t ls_realpath(const char *path, char *buf, size_t size);

size_t ls_cwd(char *buf, size_t size);

int ls_shell_move( const char *src, const char *dst );

int ls_shell_copy( const char *src, const char *dst );

int ls_shell_delete( const char *path );

int ls_shell_recycle( const char *path );

#endif // _LS_SHELL_H_
5 changes: 5 additions & 0 deletions include/lysys/ls_user.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
#define LS_DIR_USER_TEMPLATES 0x08
#define LS_DIR_USER_PUBLIC 0x09

#define LS_DIR_WINDOWS 0x1001
#define LS_DIR_SYSTEM32 0x1002
#define LS_DIR_PROGRAM_FILES 0x1003
#define LS_DIR_PROGRAM_FILES_X86 0x1004

size_t ls_username(char *name, size_t size);

size_t ls_home(char *path, size_t size);
Expand Down
300 changes: 299 additions & 1 deletion src/ls_shell.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "ls_native.h"

#include <lysys/ls_shell.h>

#include <lysys/ls_file.h>
#include <lysys/ls_core.h>

#include <string.h>
Expand Down Expand Up @@ -39,6 +39,35 @@ char *ls_strrdir(const char *path)
return (char *)last;
}

void ls_path_win32(char *path)
{
while (*path)
{
if (*path == '/')
*path = '\\';
path++;
}
}

void ls_path_unix(char *path)
{
while (*path)
{
if (*path == '\\')
*path = '/';
path++;
}
}

void ls_path_native(char *path)
{
#if LS_WINDOWS
ls_path_win32(path);
#else
ls_path_unix(path);
#endif // LS_WINDOWS
}

size_t ls_dirname(const char *path, char *buf, size_t size)
{
char *sep;
Expand Down Expand Up @@ -602,3 +631,272 @@ size_t ls_cwd(char *buf, size_t size)
return len - 1;
#endif // LS_WINDOWS
}

#if LS_WINDOWS
static int ls_parse_move_names(const char *src, const char *dst, PWCHAR wszSrc, PWCHAR wszDstName, PWCHAR wszDstDir)
{
size_t len;
PWSTR pszMatch;

len = ls_utf8_to_wchar_buf(src, wszSrc, MAX_PATH);
if (len == -1)
return -1;

len = ls_utf8_to_wchar_buf(dst, wszDstDir, MAX_PATH);
if (len == -1)
return -1;

pszMatch = (PWSTR)StrRChrW(wszDstDir, NULL, L'\\');
if (!pszMatch)
return ls_set_errno(LS_INVALID_ARGUMENT);
*pszMatch = L'\0';

wcscpy_s(wszDstName, MAX_PATH, pszMatch + 1);

return 0;
}

static IShellItem *ls_item_from_parsing_name(PCWSTR pwzPath, IBindCtx *ctx)
{
IShellItem *psi = NULL;
HRESULT hr;

hr = SHCreateItemFromParsingName(pwzPath, ctx, &IID_IShellItem, (void **)&psi);
if (FAILED(hr))
{
ls_set_errno_hresult(hr);
return NULL;
}

return psi;
}
#endif // LS_WINDOWS

int ls_shell_move(const char *src, const char *dst)
{
#if LS_WINDOWS
WCHAR wszSrc[MAX_PATH];
WCHAR wszDstName[MAX_PATH];
WCHAR wszDstDir[MAX_PATH];
int rc;
HRESULT hr;
IFileOperation *pfo = NULL;
IShellItem *psiFrom;
IShellItem *psiTo;

rc = ls_parse_move_names(src, dst, wszSrc, wszDstName, wszDstDir);
if (rc == -1)
return -1;

hr = CoCreateInstance(&CLSID_FileOperation, NULL, CLSCTX_ALL, &IID_IFileOperation, (void **)&pfo);
if (FAILED(hr))
return ls_set_errno_hresult(hr);

hr = pfo->lpVtbl->SetOperationFlags(pfo, FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT | FOF_ALLOWUNDO);
if (FAILED(hr))
{
pfo->lpVtbl->Release(pfo);
return ls_set_errno_hresult(hr);
}

psiFrom = ls_item_from_parsing_name(wszSrc, NULL);
if (!psiFrom)
{
pfo->lpVtbl->Release(pfo);
return -1;
}

psiTo = ls_item_from_parsing_name(wszDstDir, NULL);
if (!psiTo)
{
psiFrom->lpVtbl->Release(psiFrom);
pfo->lpVtbl->Release(pfo);
return -1;
}

hr = pfo->lpVtbl->MoveItem(pfo, psiFrom, psiTo, wszDstName, NULL);
if (FAILED(hr))
{
psiTo->lpVtbl->Release(psiTo);
psiFrom->lpVtbl->Release(psiFrom);
pfo->lpVtbl->Release(pfo);
return ls_set_errno_hresult(hr);
}

hr = pfo->lpVtbl->PerformOperations(pfo);

psiTo->lpVtbl->Release(psiTo);
psiFrom->lpVtbl->Release(psiFrom);
pfo->lpVtbl->Release(pfo);

return ls_set_errno_hresult(hr);
#else
return ls_move(src, dst);
#endif // LS_WINDOWS
}

int ls_shell_copy(const char *src, const char *dst)
{
#if LS_WINDOWS
WCHAR wszSrc[MAX_PATH];
WCHAR wszDst[MAX_PATH];
size_t len;
HRESULT hr;
IFileOperation *pfo = NULL;
IShellItem *psiFrom;
IShellItem *psiTo;

len = ls_utf8_to_wchar_buf(src, wszSrc, MAX_PATH);
if (len == -1)
return -1;

len = ls_utf8_to_wchar_buf(dst, wszDst, MAX_PATH);
if (len == -1)
return -1;

hr = CoCreateInstance(&CLSID_FileOperation, NULL, CLSCTX_ALL, &IID_IFileOperation, (void **)&pfo);
if (FAILED(hr))
return ls_set_errno_hresult(hr);

hr = pfo->lpVtbl->SetOperationFlags(pfo, FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT | FOF_ALLOWUNDO);
if (FAILED(hr))
{
pfo->lpVtbl->Release(pfo);
return ls_set_errno_hresult(hr);
}

psiFrom = ls_item_from_parsing_name(wszSrc, NULL);
if (!psiFrom)
{
pfo->lpVtbl->Release(pfo);
return -1;
}

psiTo = ls_item_from_parsing_name(wszDst, NULL);
if (!psiTo)
{
psiFrom->lpVtbl->Release(psiFrom);
pfo->lpVtbl->Release(pfo);
return -1;
}

hr = pfo->lpVtbl->CopyItem(pfo, psiFrom, psiTo, NULL, NULL);
if (FAILED(hr))
{
psiTo->lpVtbl->Release(psiTo);
psiFrom->lpVtbl->Release(psiFrom);
pfo->lpVtbl->Release(pfo);
return ls_set_errno_hresult(hr);
}

hr = pfo->lpVtbl->PerformOperations(pfo);

psiTo->lpVtbl->Release(psiTo);
psiFrom->lpVtbl->Release(psiFrom);
pfo->lpVtbl->Release(pfo);

return ls_set_errno_hresult(hr);
#else
return ls_copy(src, dst);
#endif // LS_WINDOWS
}

int ls_shell_delete(const char *path)
{
#if LS_WINDOWS
WCHAR szPath[MAX_PATH];
size_t len;
HRESULT hr;
IFileOperation *pfo = NULL;
IShellItem *psi;

len = ls_utf8_to_wchar_buf(path, szPath, MAX_PATH);
if (len == -1)
return -1;

hr = CoCreateInstance(&CLSID_FileOperation, NULL, CLSCTX_ALL, &IID_IFileOperation, (void **)&pfo);
if (FAILED(hr))
return ls_set_errno_hresult(hr);

hr = pfo->lpVtbl->SetOperationFlags(pfo, FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT);
if (FAILED(hr))
{
pfo->lpVtbl->Release(pfo);
return ls_set_errno_hresult(hr);
}

psi = ls_item_from_parsing_name(szPath, NULL);
if (!psi)
{
pfo->lpVtbl->Release(pfo);
return -1;
}

hr = pfo->lpVtbl->DeleteItem(pfo, psi, NULL);
if (FAILED(hr))
{
psi->lpVtbl->Release(psi);
pfo->lpVtbl->Release(pfo);
return ls_set_errno_hresult(hr);
}

hr = pfo->lpVtbl->PerformOperations(pfo);

psi->lpVtbl->Release(psi);
pfo->lpVtbl->Release(pfo);

return ls_set_errno_hresult(hr);
#else
return ls_delete(path);
#endif // LS_WINDOWS
}

int ls_shell_recycle(const char *path)
{
#if LS_WINDOWS
WCHAR szPath[MAX_PATH];
size_t len;
HRESULT hr;
IFileOperation *pfo = NULL;
IShellItem *psi;

len = ls_utf8_to_wchar_buf(path, szPath, MAX_PATH);
if (len == -1)
return -1;

hr = CoCreateInstance(&CLSID_FileOperation, NULL, CLSCTX_ALL, &IID_IFileOperation, (void **)&pfo);
if (FAILED(hr))
return ls_set_errno_hresult(hr);

hr = pfo->lpVtbl->SetOperationFlags(pfo, FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT | FOF_ALLOWUNDO);
if (FAILED(hr))
{
pfo->lpVtbl->Release(pfo);
return ls_set_errno_hresult(hr);
}

psi = ls_item_from_parsing_name(szPath, NULL);
if (!psi)
{
pfo->lpVtbl->Release(pfo);
return -1;
}

hr = pfo->lpVtbl->DeleteItem(pfo, psi, NULL);
if (FAILED(hr))
{
psi->lpVtbl->Release(psi);
pfo->lpVtbl->Release(pfo);
return ls_set_errno_hresult(hr);
}

hr = pfo->lpVtbl->PerformOperations(pfo);

psi->lpVtbl->Release(psi);
pfo->lpVtbl->Release(pfo);

return ls_set_errno_hresult(hr);
#else
return ls_delete(path);
#endif // LS_WINDOWS
}
Loading

0 comments on commit 83d4efc

Please sign in to comment.