Merge branch 'channels' of github.com:FreeRDP/FreeRDP into channels

This commit is contained in:
Marc-André Moreau 2012-10-16 20:01:54 -04:00
commit 645b1a36c9
31 changed files with 1139 additions and 322 deletions

View File

@ -21,7 +21,7 @@ macro(add_channel_client _channel_prefix _channel_name)
add_subdirectory(client)
if(${_channel_prefix}_CLIENT_STATIC)
set(CHANNEL_STATIC_CLIENT_MODULES ${CHANNEL_STATIC_CLIENT_MODULES} ${_channel_prefix} PARENT_SCOPE)
set(${_channel_prefix}_CLIENT_NAME ${_channel_name} PARENT_SCOPE)
set(${_channel_prefix}_CLIENT_NAME ${${_channel_prefix}_CLIENT_NAME} PARENT_SCOPE)
set(${_channel_prefix}_CLIENT_CHANNEL ${${_channel_prefix}_CLIENT_CHANNEL} PARENT_SCOPE)
set(${_channel_prefix}_CLIENT_ENTRY ${${_channel_prefix}_CLIENT_ENTRY} PARENT_SCOPE)
set(CHANNEL_STATIC_CLIENT_ENTRIES ${CHANNEL_STATIC_CLIENT_ENTRIES} ${${_channel_prefix}_CLIENT_ENTRY} PARENT_SCOPE)
@ -39,7 +39,7 @@ macro(add_channel_server _channel_prefix _channel_name)
endif()
endmacro(add_channel_server)
macro(add_channel_client_library _module_prefix _module_name _plugin _entry)
macro(add_channel_client_library _module_prefix _module_name _channel_name _plugin _entry)
if(_plugin AND MSVC AND (NOT STATIC_CHANNELS))
set(${_module_prefix}_SRCS ${${_module_prefix}_SRCS} module.def)
@ -50,7 +50,7 @@ macro(add_channel_client_library _module_prefix _module_name _plugin _entry)
else()
set(${_module_prefix}_STATIC ON PARENT_SCOPE)
set(${_module_prefix}_NAME ${_module_name} PARENT_SCOPE)
set(${_module_prefix}_CHANNEL ${_module_name} PARENT_SCOPE)
set(${_module_prefix}_CHANNEL ${_channel_name} PARENT_SCOPE)
set(${_module_prefix}_ENTRY ${_entry} PARENT_SCOPE)
add_library(${_module_name} STATIC ${${_module_prefix}_SRCS})
endif()

View File

@ -25,7 +25,7 @@ set(${MODULE_PREFIX}_SRCS
include_directories(..)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} TRUE "DVCPluginEntry")
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")

View File

@ -26,7 +26,7 @@ set(${MODULE_PREFIX}_SRCS
cliprdr_main.c
cliprdr_main.h)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} FALSE "VirtualChannelEntry")
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")

View File

@ -31,7 +31,7 @@ if(WIN32)
dirent.h)
endif()
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} TRUE "DeviceServiceEntry")
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DeviceServiceEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")

View File

@ -26,7 +26,7 @@ set(${MODULE_PREFIX}_SRCS
dvcman.c
dvcman.h)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} FALSE "VirtualChannelEntry")
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")

View File

@ -22,7 +22,7 @@ string(TOUPPER "CHANNEL_${CHANNEL_NAME}_CLIENT" MODULE_PREFIX)
set(${MODULE_PREFIX}_SRCS
parallel_main.c)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} TRUE "DeviceServiceEntry")
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DeviceServiceEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")

View File

@ -38,7 +38,7 @@ if(WIN32)
printer_win.h)
endif()
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} TRUE "DeviceServiceEntry")
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DeviceServiceEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")

View File

@ -25,7 +25,7 @@ set(${MODULE_PREFIX}_SRCS
rail_orders.c
rail_orders.h)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} FALSE "VirtualChannelEntry")
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")

View File

@ -29,7 +29,7 @@ set(${MODULE_PREFIX}_SRCS
rdpdr_capabilities.c
rdpdr_capabilities.h)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} FALSE "VirtualChannelEntry")
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")

View File

@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
rdpsnd_main.c
rdpsnd_main.h)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} FALSE "VirtualChannelEntry")
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")

View File

@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
skel_main.c
skel_main.h)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} TRUE "DVCPluginEntry")
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")

View File

@ -25,7 +25,7 @@ set(${MODULE_PREFIX}_SRCS
serial_constants.h
serial_main.c)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} TRUE "DeviceServiceEntry")
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DeviceServiceEntry")
set_target_properties(serial PROPERTIES PREFIX "")

View File

@ -24,7 +24,7 @@ set(${MODULE_PREFIX}_SRCS
include_directories(${PCSC_INCLUDE_DIRS})
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} TRUE "DVCPluginEntry")
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")

View File

@ -38,7 +38,7 @@ set(${MODULE_PREFIX}_SRCS
include_directories(..)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} TRUE "DVCPluginEntry")
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")

View File

@ -33,7 +33,7 @@ set(${MODULE_PREFIX}_SRCS
include_directories(..)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} TRUE "DVCPluginEntry")
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")

View File

@ -107,4 +107,3 @@ void wf_cliprdr_check_owner(wfInfo* wfi)
{
}

View File

@ -119,6 +119,27 @@ LRESULT CALLBACK wf_ll_kbd_proc(int nCode, WPARAM wParam, LPARAM lParam)
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
static int xf_event_process_WM_MOUSEWHEEL(wfInfo* wfi, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
int delta;
int flags;
rdpInput* input;
DefWindowProc(hWnd, Msg, wParam, lParam);
input = wfi->instance->input;
delta = ((signed short)HIWORD(wParam)); /* GET_WHEEL_DELTA_WPARAM(wParam); */
if (delta > 0)
{
flags = PTR_FLAGS_WHEEL | 0x0078;
}
else
{
flags = PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x0088;
}
input->MouseEvent(input, flags, 0, 0);
return 0;
}
LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
@ -141,7 +162,7 @@ LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
x = ps.rcPaint.left;
y = ps.rcPaint.top;
w = ps.rcPaint.right - ps.rcPaint.left + 1;
@ -174,8 +195,15 @@ LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam
input->MouseEvent(input, PTR_FLAGS_MOVE, X_POS(lParam), Y_POS(lParam));
break;
case WM_MOUSEWHEEL:
xf_event_process_WM_MOUSEWHEEL(wfi, hWnd, Msg, wParam, lParam, FALSE);
break;
case WM_SETCURSOR:
SetCursor(wfi->cursor);
if (LOWORD(lParam) == HTCLIENT)
SetCursor(wfi->cursor);
else
DefWindowProc(hWnd, Msg, wParam, lParam);
break;
default:
@ -198,7 +226,10 @@ LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam
break;
case WM_SETCURSOR:
SetCursor(g_default_cursor);
if (LOWORD(lParam) == HTCLIENT)
SetCursor(g_default_cursor);
else
DefWindowProc(hWnd, Msg, wParam, lParam);
break;
case WM_SETFOCUS:

View File

@ -142,7 +142,7 @@ HBRUSH wf_create_brush(wfInfo * wfi, rdpBrush* brush, UINT32 color, int bpp)
{
for (i = 0; i != 8; i++)
ipattern[7 - i] = brush->data[i];
cdata = wf_glyph_convert(wfi, 8, 8, ipattern);
pattern = CreateBitmap(8, 8, 1, 1, cdata);
lbr.lbHatch = (ULONG_PTR) pattern;
@ -342,7 +342,7 @@ void wf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to)
wf_set_rop2(wfi->drawing->hdc, line_to->bRop2);
org_pen = (HPEN) SelectObject(wfi->drawing->hdc, pen);
MoveToEx(wfi->drawing->hdc, line_to->nXStart, line_to->nYStart, NULL);
LineTo(wfi->drawing->hdc, line_to->nXEnd, line_to->nYEnd);
@ -469,7 +469,7 @@ void wf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
wfi->image->_bitmap.data = (BYTE*) realloc(wfi->image->_bitmap.data, wfi->image->_bitmap.width * wfi->image->_bitmap.height * 4);
freerdp_image_flip(nsc_context->bmpdata, wfi->image->_bitmap.data, wfi->image->_bitmap.width, wfi->image->_bitmap.height, 32);
BitBlt(wfi->primary->hdc, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height, wfi->image->hdc, 0, 0, GDI_SRCCOPY);
}
}
else if (surface_bits_command->codecID == CODEC_ID_NONE)
{
wfi->image->_bitmap.width = surface_bits_command->width;

View File

@ -27,6 +27,8 @@
#include "wf_gdi.h"
#include "wf_graphics.h"
extern HINSTANCE g_hInstance; /* in wfreerdp.c */
HBITMAP wf_create_dib(wfInfo* wfi, int width, int height, int bpp, BYTE* data, BYTE** pdata)
{
HDC hdc;
@ -78,7 +80,7 @@ wfBitmap* wf_image_new(wfInfo* wfi, int width, int height, int bpp, BYTE* data)
image->org_bitmap = (HBITMAP) SelectObject(image->hdc, image->bitmap);
ReleaseDC(NULL, hdc);
return image;
}
@ -118,7 +120,7 @@ void wf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap)
void wf_Bitmap_Free(rdpContext* context, rdpBitmap* bitmap)
{
wfBitmap* wf_bitmap = (wfBitmap*) bitmap;
if (wf_bitmap != 0)
{
SelectObject(wf_bitmap->hdc, wf_bitmap->org_bitmap);
@ -189,17 +191,64 @@ void wf_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary)
void wf_Pointer_New(rdpContext* context, rdpPointer* pointer)
{
HCURSOR hCur;
unsigned char am[32 * 4];
unsigned char xm[32 * 4];
int i, j, ii;
int width, height, bpp;
width = pointer->width;
height = pointer->height;
bpp = pointer->xorBpp;
if ((bpp != 1 && bpp != 8 && bpp != 15 && bpp != 16 && bpp != 24 && bpp != 32) ||
width > 32 || height > 32)
{
printf("wf_Pointer_New: Unsupported Cursor width = %u, height = %u, xorBpp = %u\n", width, height, bpp);
return;
}
memset(am, 0, 32 * 4);
memset(xm, 0, 32 * 4);
for (i = 0; i < 32; i++)
{
ii = (bpp == 1) ? i : (height - 1) - i;
for (j = 0; j < 32; j++)
{
if (freerdp_get_pixel(pointer->andMaskData, j, i, width, height, 1))
{
freerdp_set_pixel(am, j, ii, width, height, 1, 1);
}
if (freerdp_get_pixel(pointer->xorMaskData, j, i, width, height, bpp))
{
freerdp_set_pixel(xm, j, ii, width, height, 1, 1);
}
}
}
hCur = CreateCursor(g_hInstance, pointer->xPos, pointer->yPos, pointer->width, pointer->height, am, xm);
((wfPointer*) pointer)->cursor = hCur;
}
void wf_Pointer_Free(rdpContext* context, rdpPointer* pointer)
{
HCURSOR hCur;
hCur = ((wfPointer*) pointer)->cursor;
if (hCur != 0)
DestroyCursor(hCur);
}
void wf_Pointer_Set(rdpContext* context, rdpPointer* pointer)
{
wfInfo* wfi;
HCURSOR hCur;
wfi = ((wfContext*) context)->wfi;
hCur = ((wfPointer*) pointer)->cursor;
if (hCur != NULL)
{
SetCursor(hCur);
wfi->cursor = hCur;
}
}
void wf_Pointer_SetNull(rdpContext* context)

View File

@ -29,4 +29,4 @@ void wf_process_rail_event(wfInfo* wfi, rdpChannels* chanman, RDP_EVENT* event);
void wf_rail_adjust_position(wfInfo* wfi, rdpWindow *window);
void wf_rail_end_local_move(wfInfo* wfi, rdpWindow *window);
#endif
#endif

View File

@ -24,4 +24,4 @@
#include "wfreerdp.h"
#endif
#endif

View File

@ -50,6 +50,7 @@ typedef struct wf_bitmap wfBitmap;
struct wf_pointer
{
rdpPointer pointer;
HCURSOR cursor;
};
typedef struct wf_pointer wfPointer;

View File

@ -237,6 +237,9 @@ typedef CLRCONV* HCLRCONV;
typedef BYTE* (*p_freerdp_image_convert)(BYTE* srcData, BYTE* dstData, int width, int height, int srcBpp, int dstBpp, HCLRCONV clrconv);
FREERDP_API int freerdp_get_pixel(BYTE* data, int x, int y, int width, int height, int bpp);
FREERDP_API void freerdp_set_pixel(BYTE* data, int x, int y, int width, int height, int bpp, int pixel);
FREERDP_API BYTE* freerdp_image_convert(BYTE* srcData, BYTE *dstData, int width, int height, int srcBpp, int dstBpp, HCLRCONV clrconv);
FREERDP_API BYTE* freerdp_glyph_convert(int width, int height, BYTE* data);
FREERDP_API void freerdp_bitmap_flip(BYTE * src, BYTE * dst, int scanLineSz, int height);

View File

@ -28,7 +28,6 @@
#ifdef WITH_JPEG
#define XMD_H
#define HAVE_BOOLEAN
#include <jpeglib.h>

View File

@ -159,6 +159,95 @@ WINPR_API HRESULT PathCchRemoveFileSpecW(PWSTR pszPath, size_t cchPath);
#define PathCchRemoveFileSpec PathCchRemoveFileSpecA
#endif
/* Unix-style Paths */
WINPR_API HRESULT PathCchAddSlashA(PSTR pszPath, size_t cchPath);
WINPR_API HRESULT PathCchAddSlashW(PWSTR pszPath, size_t cchPath);
WINPR_API HRESULT PathCchAddSlashExA(PSTR pszPath, size_t cchPath, PSTR* ppszEnd, size_t* pcchRemaining);
WINPR_API HRESULT PathCchAddSlashExW(PWSTR pszPath, size_t cchPath, PWSTR* ppszEnd, size_t* pcchRemaining);
WINPR_API HRESULT UnixPathCchAddExtensionA(PSTR pszPath, size_t cchPath, PCSTR pszExt);
WINPR_API HRESULT UnixPathCchAddExtensionW(PWSTR pszPath, size_t cchPath, PCWSTR pszExt);
WINPR_API HRESULT UnixPathCchAppendA(PSTR pszPath, size_t cchPath, PCSTR pszMore);
WINPR_API HRESULT UnixPathCchAppendW(PWSTR pszPath, size_t cchPath, PCWSTR pszMore);
WINPR_API HRESULT UnixPathAllocCombineA(PCSTR pszPathIn, PCSTR pszMore, unsigned long dwFlags, PSTR* ppszPathOut);
WINPR_API HRESULT UnixPathAllocCombineW(PCWSTR pszPathIn, PCWSTR pszMore, unsigned long dwFlags, PWSTR* ppszPathOut);
#ifdef UNICODE
#define PathCchAddSlash PathCchAddSlashW
#define PathCchAddSlashEx PathCchAddSlashExW
#define UnixPathCchAddExtension UnixPathCchAddExtensionW
#define UnixPathCchAppend UnixPathCchAppendW
#define UnixPathAllocCombine UnixPathAllocCombineW
#else
#define PathCchAddSlash PathCchAddSlashA
#define PathCchAddSlashEx PathCchAddSlashExA
#define UnixPathCchAddExtension UnixPathCchAddExtensionA
#define UnixPathCchAppend UnixPathCchAppendA
#define UnixPathAllocCombine UnixPathAllocCombineA
#endif
/* Native-style Paths */
WINPR_API HRESULT PathCchAddSeparatorA(PSTR pszPath, size_t cchPath);
WINPR_API HRESULT PathCchAddSeparatorW(PWSTR pszPath, size_t cchPath);
WINPR_API HRESULT PathCchAddSeparatorExA(PSTR pszPath, size_t cchPath, PSTR* ppszEnd, size_t* pcchRemaining);
WINPR_API HRESULT PathCchAddSeparatorExW(PWSTR pszPath, size_t cchPath, PWSTR* ppszEnd, size_t* pcchRemaining);
WINPR_API HRESULT NativePathCchAddExtensionA(PSTR pszPath, size_t cchPath, PCSTR pszExt);
WINPR_API HRESULT NativePathCchAddExtensionW(PWSTR pszPath, size_t cchPath, PCWSTR pszExt);
WINPR_API HRESULT NativePathCchAppendA(PSTR pszPath, size_t cchPath, PCSTR pszMore);
WINPR_API HRESULT NativePathCchAppendW(PWSTR pszPath, size_t cchPath, PCWSTR pszMore);
WINPR_API HRESULT NativePathAllocCombineA(PCSTR pszPathIn, PCSTR pszMore, unsigned long dwFlags, PSTR* ppszPathOut);
WINPR_API HRESULT NativePathAllocCombineW(PCWSTR pszPathIn, PCWSTR pszMore, unsigned long dwFlags, PWSTR* ppszPathOut);
#ifdef UNICODE
#define PathCchAddSeparator PathCchAddSeparatorW
#define PathCchAddSeparatorEx PathCchAddSeparatorExW
#define NativePathCchAddExtension NativePathCchAddExtensionW
#define NativePathCchAppend NativePathCchAppendW
#define NativePathAllocCombine NativePathAllocCombineW
#else
#define PathCchAddSeparator PathCchAddSeparatorA
#define PathCchAddSeparatorEx PathCchAddSeparatorExA
#define NativePathCchAddExtension NativePathCchAddExtensionA
#define NativePathCchAppend NativePathCchAppendA
#define NativePathAllocCombine NativePathAllocCombineA
#endif
/* Path Portability Functions */
#define PATH_STYLE_WINDOWS 0x00000001
#define PATH_STYLE_UNIX 0x00000002
#define PATH_STYLE_NATIVE 0x00000003
#define PATH_SHARED_LIB_EXT_WITH_DOT 0x00000001
#define PATH_SHARED_LIB_EXT_APPLE_SO 0x00000002
#define PATH_SHARED_LIB_EXT_EXPLICIT 0x80000000
#define PATH_SHARED_LIB_EXT_EXPLICIT_DLL 0x80000001
#define PATH_SHARED_LIB_EXT_EXPLICIT_SO 0x80000002
#define PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB 0x80000003
WINPR_API HRESULT PathCchConvertStyleA(PSTR pszPath, size_t cchPath, unsigned long dwFlags);
WINPR_API HRESULT PathCchConvertStyleW(PWSTR pszPath, size_t cchPath, unsigned long dwFlags);
WINPR_API PCSTR PathGetSharedLibraryExtensionA(unsigned long dwFlags);
WINPR_API PCWSTR PathGetSharedLibraryExtensionW(unsigned long dwFlags);
#ifdef UNICODE
#define PathCchConvertStyle PathCchConvertStyleW
#define PathGetSharedLibraryExtension PathGetSharedLibraryExtensionW
#else
#define PathCchConvertStyle PathCchConvertStyleA
#define PathGetSharedLibraryExtension PathGetSharedLibraryExtensionA
#endif
#endif
#endif /* WINPR_PATH_H */

View File

@ -0,0 +1,143 @@
/*
#define DEFINE_UNICODE FALSE
#define _PATH_SEPARATOR_CHR '\\'
#define _PATH_SEPARATOR_STR "\\"
#define PATH_ALLOC_COMBINE PathAllocCombineA
*/
#if DEFINE_UNICODE
HRESULT PATH_ALLOC_COMBINE(PCWSTR pszPathIn, PCWSTR pszMore, unsigned long dwFlags, PWSTR* ppszPathOut)
{
#ifdef _WIN32
PWSTR pszPathOut;
BOOL backslashIn;
BOOL backslashMore;
int pszMoreLength;
int pszPathInLength;
int pszPathOutLength;
if (!pszPathIn)
return S_FALSE;
if (!pszMore)
return S_FALSE;
pszPathInLength = lstrlenW(pszPathIn);
pszMoreLength = lstrlenW(pszMore);
backslashIn = (pszPathIn[pszPathInLength - 1] == _PATH_SEPARATOR_CHR) ? TRUE : FALSE;
backslashMore = (pszMore[0] == _PATH_SEPARATOR_CHR) ? TRUE : FALSE;
if (backslashMore)
{
if ((pszPathIn[1] == ':') && (pszPathIn[2] == _PATH_SEPARATOR_CHR))
{
size_t sizeOfBuffer;
pszPathOutLength = 2 + pszMoreLength;
sizeOfBuffer = (pszPathOutLength + 1) * 2;
pszPathOut = (PWSTR) HeapAlloc(GetProcessHeap(), 0, sizeOfBuffer * 2);
swprintf_s(pszPathOut, sizeOfBuffer, L"%c:%s", pszPathIn[0], pszMore);
*ppszPathOut = pszPathOut;
return S_OK;
}
}
else
{
size_t sizeOfBuffer;
pszPathOutLength = pszPathInLength + pszMoreLength;
sizeOfBuffer = (pszPathOutLength + 1) * 2;
pszPathOut = (PWSTR) HeapAlloc(GetProcessHeap(), 0, sizeOfBuffer * 2);
if (backslashIn)
swprintf_s(pszPathOut, sizeOfBuffer, L"%s%s", pszPathIn, pszMore);
else
swprintf_s(pszPathOut, sizeOfBuffer, L"%s" L _PATH_SEPARATOR_STR L"%s", pszPathIn, pszMore);
*ppszPathOut = pszPathOut;
return S_OK;
}
#endif
return S_OK;
}
#else
HRESULT PATH_ALLOC_COMBINE(PCSTR pszPathIn, PCSTR pszMore, unsigned long dwFlags, PSTR* ppszPathOut)
{
PSTR pszPathOut;
BOOL backslashIn;
BOOL backslashMore;
int pszMoreLength;
int pszPathInLength;
int pszPathOutLength;
if (!pszPathIn)
return S_FALSE;
if (!pszMore)
return S_FALSE;
pszPathInLength = lstrlenA(pszPathIn);
pszMoreLength = lstrlenA(pszMore);
backslashIn = (pszPathIn[pszPathInLength - 1] == _PATH_SEPARATOR_CHR) ? TRUE : FALSE;
backslashMore = (pszMore[0] == _PATH_SEPARATOR_CHR) ? TRUE : FALSE;
if (backslashMore)
{
if ((pszPathIn[1] == ':') && (pszPathIn[2] == _PATH_SEPARATOR_CHR))
{
size_t sizeOfBuffer;
pszPathOutLength = 2 + pszMoreLength;
sizeOfBuffer = (pszPathOutLength + 1) * 2;
pszPathOut = (PSTR) HeapAlloc(GetProcessHeap(), 0, sizeOfBuffer * 2);
sprintf_s(pszPathOut, sizeOfBuffer, "%c:%s", pszPathIn[0], pszMore);
*ppszPathOut = pszPathOut;
return S_OK;
}
}
else
{
size_t sizeOfBuffer;
pszPathOutLength = pszPathInLength + pszMoreLength;
sizeOfBuffer = (pszPathOutLength + 1) * 2;
pszPathOut = (PSTR) HeapAlloc(GetProcessHeap(), 0, sizeOfBuffer * 2);
if (backslashIn)
sprintf_s(pszPathOut, sizeOfBuffer, "%s%s", pszPathIn, pszMore);
else
sprintf_s(pszPathOut, sizeOfBuffer, "%s" _PATH_SEPARATOR_STR "%s", pszPathIn, pszMore);
*ppszPathOut = pszPathOut;
return S_OK;
}
return S_OK;
}
#endif
/*
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef _PATH_SEPARATOR_STR
#undef PATH_ALLOC_COMBINE
*/

View File

@ -0,0 +1,100 @@
/*
#define DEFINE_UNICODE FALSE
#define _PATH_SEPARATOR_CHR '\\'
#define PATH_CCH_ADD_EXTENSION PathCchAddExtensionA
*/
#if DEFINE_UNICODE
HRESULT PATH_CCH_ADD_EXTENSION(PWSTR pszPath, size_t cchPath, PCWSTR pszExt)
{
#ifdef _WIN32
LPWSTR pDot;
BOOL bExtDot;
LPWSTR pBackslash;
size_t pszExtLength;
size_t pszPathLength;
if (!pszPath)
return S_FALSE;
if (!pszExt)
return S_FALSE;
pszExtLength = lstrlenW(pszExt);
pszPathLength = lstrlenW(pszPath);
bExtDot = (pszExt[0] == '.') ? TRUE : FALSE;
pDot = wcsrchr(pszPath, '.');
pBackslash = wcsrchr(pszPath, _PATH_SEPARATOR_CHR);
if (pDot && pBackslash)
{
if (pDot > pBackslash)
return S_FALSE;
}
if (cchPath > pszPathLength + pszExtLength + ((bExtDot) ? 0 : 1))
{
if (bExtDot)
swprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, L"%s", pszExt);
else
swprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, L".%s", pszExt);
return S_OK;
}
#endif
return S_FALSE;
}
#else
HRESULT PATH_CCH_ADD_EXTENSION(PSTR pszPath, size_t cchPath, PCSTR pszExt)
{
CHAR* pDot;
BOOL bExtDot;
CHAR* pBackslash;
size_t pszExtLength;
size_t pszPathLength;
if (!pszPath)
return S_FALSE;
if (!pszExt)
return S_FALSE;
pszExtLength = lstrlenA(pszExt);
pszPathLength = lstrlenA(pszPath);
bExtDot = (pszExt[0] == '.') ? TRUE : FALSE;
pDot = strrchr(pszPath, '.');
pBackslash = strrchr(pszPath, _PATH_SEPARATOR_CHR);
if (pDot && pBackslash)
{
if (pDot > pBackslash)
return S_FALSE;
}
if (cchPath > pszPathLength + pszExtLength + ((bExtDot) ? 0 : 1))
{
if (bExtDot)
sprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, "%s", pszExt);
else
sprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, ".%s", pszExt);
return S_OK;
}
return S_FALSE;
}
#endif
/*
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_EXTENSION
*/

View File

@ -1,7 +1,7 @@
/*
#define DEFINE_UNICODE FALSE
#define PATH_SEPARATOR '\\'
#define _PATH_SEPARATOR_CHR '\\'
#define PATH_CCH_ADD_SEPARATOR PathCchAddBackslashA
*/
@ -16,12 +16,12 @@ HRESULT PATH_CCH_ADD_SEPARATOR(PWSTR pszPath, size_t cchPath)
pszPathLength = lstrlenW(pszPath);
if (pszPath[pszPathLength - 1] == PATH_SEPARATOR)
if (pszPath[pszPathLength - 1] == _PATH_SEPARATOR_CHR)
return S_FALSE;
if (cchPath > (pszPathLength + 1))
{
pszPath[pszPathLength] = PATH_SEPARATOR;
pszPath[pszPathLength] = _PATH_SEPARATOR_CHR;
pszPath[pszPathLength + 1] = '\0';
return S_OK;
@ -41,12 +41,12 @@ HRESULT PATH_CCH_ADD_SEPARATOR(PSTR pszPath, size_t cchPath)
pszPathLength = lstrlenA(pszPath);
if (pszPath[pszPathLength - 1] == PATH_SEPARATOR)
if (pszPath[pszPathLength - 1] == _PATH_SEPARATOR_CHR)
return S_FALSE;
if (cchPath > (pszPathLength + 1))
{
pszPath[pszPathLength] = PATH_SEPARATOR;
pszPath[pszPathLength] = _PATH_SEPARATOR_CHR;
pszPath[pszPathLength + 1] = '\0';
return S_OK;
@ -59,7 +59,7 @@ HRESULT PATH_CCH_ADD_SEPARATOR(PSTR pszPath, size_t cchPath)
/*
#undef DEFINE_UNICODE
#undef PATH_SEPARATOR
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_SEPARATOR
*/

View File

@ -1,7 +1,7 @@
/*
#define DEFINE_UNICODE FALSE
#define PATH_SEPARATOR '\\'
#define _PATH_SEPARATOR_CHR '\\'
#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddBackslashExA
*/
@ -16,12 +16,12 @@ HRESULT PATH_CCH_ADD_SEPARATOR_EX(PWSTR pszPath, size_t cchPath, PWSTR* ppszEnd,
pszPathLength = lstrlenW(pszPath);
if (pszPath[pszPathLength - 1] == PATH_SEPARATOR)
if (pszPath[pszPathLength - 1] == _PATH_SEPARATOR_CHR)
return S_FALSE;
if (cchPath > (pszPathLength + 1))
{
pszPath[pszPathLength] = PATH_SEPARATOR;
pszPath[pszPathLength] = _PATH_SEPARATOR_CHR;
pszPath[pszPathLength + 1] = '\0';
return S_OK;
@ -41,12 +41,12 @@ HRESULT PATH_CCH_ADD_SEPARATOR_EX(PSTR pszPath, size_t cchPath, PSTR* ppszEnd, s
pszPathLength = lstrlenA(pszPath);
if (pszPath[pszPathLength - 1] == PATH_SEPARATOR)
if (pszPath[pszPathLength - 1] == _PATH_SEPARATOR_CHR)
return S_FALSE;
if (cchPath > (pszPathLength + 1))
{
pszPath[pszPathLength] = PATH_SEPARATOR;
pszPath[pszPathLength] = _PATH_SEPARATOR_CHR;
pszPath[pszPathLength + 1] = '\0';
return S_OK;
@ -59,7 +59,7 @@ HRESULT PATH_CCH_ADD_SEPARATOR_EX(PSTR pszPath, size_t cchPath, PSTR* ppszEnd, s
/*
#undef DEFINE_UNICODE
#undef PATH_SEPARATOR
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_SEPARATOR_EX
*/

View File

@ -0,0 +1,117 @@
/*
#define DEFINE_UNICODE FALSE
#define _PATH_SEPARATOR_CHR '\\'
#define _PATH_SEPARATOR_STR "\\"
#define PATH_CCH_APPEND PathCchAppendA
*/
#if DEFINE_UNICODE
HRESULT PATH_CCH_APPEND(PWSTR pszPath, size_t cchPath, PCWSTR pszMore)
{
#ifdef _WIN32
BOOL pathBackslash;
BOOL moreBackslash;
size_t pszMoreLength;
size_t pszPathLength;
if (!pszPath)
return S_FALSE;
if (!pszMore)
return S_FALSE;
pszMoreLength = lstrlenW(pszMore);
pszPathLength = lstrlenW(pszPath);
pathBackslash = (pszPath[pszPathLength - 1] == _PATH_SEPARATOR_CHR) ? TRUE : FALSE;
moreBackslash = (pszMore[0] == _PATH_SEPARATOR_CHR) ? TRUE : FALSE;
if (pathBackslash && moreBackslash)
{
if ((pszPathLength + pszMoreLength - 1) < cchPath)
{
swprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, L"%s", &pszMore[1]);
return S_OK;
}
}
else if ((pathBackslash && !moreBackslash) || (!pathBackslash && moreBackslash))
{
if ((pszPathLength + pszMoreLength) < cchPath)
{
swprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, L"%s", pszMore);
return S_OK;
}
}
else if (!pathBackslash && !moreBackslash)
{
if ((pszPathLength + pszMoreLength + 1) < cchPath)
{
swprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, L _PATH_SEPARATOR_STR L"%s", pszMore);
return S_OK;
}
}
#endif
return S_FALSE;
}
#else
HRESULT PATH_CCH_APPEND(PSTR pszPath, size_t cchPath, PCSTR pszMore)
{
BOOL pathBackslash;
BOOL moreBackslash;
size_t pszMoreLength;
size_t pszPathLength;
if (!pszPath)
return S_FALSE;
if (!pszMore)
return S_FALSE;
pszMoreLength = lstrlenA(pszMore);
pszPathLength = lstrlenA(pszPath);
pathBackslash = (pszPath[pszPathLength - 1] == _PATH_SEPARATOR_CHR) ? TRUE : FALSE;
moreBackslash = (pszMore[0] == _PATH_SEPARATOR_CHR) ? TRUE : FALSE;
if (pathBackslash && moreBackslash)
{
if ((pszPathLength + pszMoreLength - 1) < cchPath)
{
sprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, "%s", &pszMore[1]);
return S_OK;
}
}
else if ((pathBackslash && !moreBackslash) || (!pathBackslash && moreBackslash))
{
if ((pszPathLength + pszMoreLength) < cchPath)
{
sprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, "%s", pszMore);
return S_OK;
}
}
else if (!pathBackslash && !moreBackslash)
{
if ((pszPathLength + pszMoreLength + 1) < cchPath)
{
sprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, _PATH_SEPARATOR_STR "%s", pszMore);
return S_OK;
}
}
return S_FALSE;
}
#endif
/*
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef _PATH_SEPARATOR_STR
#undef PATH_CCH_APPEND
*/

View File

@ -27,22 +27,94 @@
#include <winpr/path.h>
#define PATH_SLASH_STR "/"
#define PATH_SLASH_CHR '/'
#define PATH_BACKSLASH_STR "\\"
#define PATH_BACKSLASH_CHR '\\'
#ifdef _WIN32
#define PATH_SEPARATOR_STR PATH_BACKSLASH_STR
#define PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
#else
#define PATH_SEPARATOR_STR PATH_SLASH_STR
#define PATH_SEPARATOR_CHR PATH_SLASH_CHR
#endif
#define SHARED_LIBRARY_EXT_DLL "dll"
#define SHARED_LIBRARY_EXT_SO "so"
#define SHARED_LIBRARY_EXT_DYLIB "dylib"
#ifdef _WIN32
#define SHARED_LIBRARY_EXT SHARED_LIBRARY_EXT_DLL
#elif __APPLE__
#define SHARED_LIBRARY_EXT SHARED_LIBRARY_EXT_DYLIB
#else
#define SHARED_LIBRARY_EXT SHARED_LIBRARY_EXT_SO
#endif
/*
* PathCchAddBackslash
*/
/* Windows-style Paths */
#define DEFINE_UNICODE FALSE
#define PATH_SEPARATOR '\\'
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
#define PATH_CCH_ADD_SEPARATOR PathCchAddBackslashA
#include "include/PathCchAddSeparator.c"
#undef DEFINE_UNICODE
#undef PATH_SEPARATOR
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_SEPARATOR
#define DEFINE_UNICODE TRUE
#define PATH_SEPARATOR '\\'
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
#define PATH_CCH_ADD_SEPARATOR PathCchAddBackslashW
#include "include/PathCchAddSeparator.c"
#undef DEFINE_UNICODE
#undef PATH_SEPARATOR
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_SEPARATOR
/* Unix-style Paths */
#define DEFINE_UNICODE FALSE
#define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
#define PATH_CCH_ADD_SEPARATOR PathCchAddSlashA
#include "include/PathCchAddSeparator.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_SEPARATOR
#define DEFINE_UNICODE TRUE
#define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
#define PATH_CCH_ADD_SEPARATOR PathCchAddSlashW
#include "include/PathCchAddSeparator.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_SEPARATOR
/* Native-style Paths */
#define DEFINE_UNICODE FALSE
#define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
#define PATH_CCH_ADD_SEPARATOR PathCchAddSeparatorA
#include "include/PathCchAddSeparator.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_SEPARATOR
#define DEFINE_UNICODE TRUE
#define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
#define PATH_CCH_ADD_SEPARATOR PathCchAddSeparatorW
#include "include/PathCchAddSeparator.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_SEPARATOR
/*
* PathCchRemoveBackslash
*/
HRESULT PathCchRemoveBackslashA(PSTR pszPath, size_t cchPath)
{
return 0;
@ -53,20 +125,62 @@ HRESULT PathCchRemoveBackslashW(PWSTR pszPath, size_t cchPath)
return 0;
}
/*
* PathCchAddBackslashEx
*/
/* Windows-style Paths */
#define DEFINE_UNICODE FALSE
#define PATH_SEPARATOR '\\'
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddBackslashExA
#include "include/PathCchAddSeparatorEx.c"
#undef DEFINE_UNICODE
#undef PATH_SEPARATOR
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_SEPARATOR_EX
#define DEFINE_UNICODE TRUE
#define PATH_SEPARATOR '\\'
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddBackslashExW
#include "include/PathCchAddSeparatorEx.c"
#undef DEFINE_UNICODE
#undef PATH_SEPARATOR
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_SEPARATOR_EX
/* Unix-style Paths */
#define DEFINE_UNICODE FALSE
#define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSlashExA
#include "include/PathCchAddSeparatorEx.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_SEPARATOR_EX
#define DEFINE_UNICODE TRUE
#define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSlashExW
#include "include/PathCchAddSeparatorEx.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_SEPARATOR_EX
/* Native-style Paths */
#define DEFINE_UNICODE FALSE
#define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSeparatorExA
#include "include/PathCchAddSeparatorEx.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_SEPARATOR_EX
#define DEFINE_UNICODE TRUE
#define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSeparatorExW
#include "include/PathCchAddSeparatorEx.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_SEPARATOR_EX
HRESULT PathCchRemoveBackslashExA(PSTR pszPath, size_t cchPath, PSTR* ppszEnd, size_t* pcchRemaining)
@ -79,182 +193,93 @@ HRESULT PathCchRemoveBackslashExW(PWSTR pszPath, size_t cchPath, PWSTR* ppszEnd,
return 0;
}
HRESULT PathCchAddExtensionA(PSTR pszPath, size_t cchPath, PCSTR pszExt)
{
CHAR* pDot;
BOOL bExtDot;
CHAR* pBackslash;
size_t pszExtLength;
size_t pszPathLength;
/*
* PathCchAddExtension
*/
if (!pszPath)
return S_FALSE;
/* Windows-style Paths */
if (!pszExt)
return S_FALSE;
#define DEFINE_UNICODE FALSE
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
#define PATH_CCH_ADD_EXTENSION PathCchAddExtensionA
#include "include/PathCchAddExtension.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_EXTENSION
pszExtLength = lstrlenA(pszExt);
pszPathLength = lstrlenA(pszPath);
bExtDot = (pszExt[0] == '.') ? TRUE : FALSE;
#define DEFINE_UNICODE TRUE
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
#define PATH_CCH_ADD_EXTENSION PathCchAddExtensionW
#include "include/PathCchAddExtension.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_EXTENSION
pDot = strrchr(pszPath, '.');
pBackslash = strrchr(pszPath, '\\');
/* Unix-style Paths */
if (pDot && pBackslash)
{
if (pDot > pBackslash)
return S_FALSE;
}
#define DEFINE_UNICODE FALSE
#define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
#define PATH_CCH_ADD_EXTENSION UnixPathCchAddExtensionA
#include "include/PathCchAddExtension.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_EXTENSION
if (cchPath > pszPathLength + pszExtLength + ((bExtDot) ? 0 : 1))
{
if (bExtDot)
sprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, "%s", pszExt);
else
sprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, ".%s", pszExt);
#define DEFINE_UNICODE TRUE
#define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
#define PATH_CCH_ADD_EXTENSION UnixPathCchAddExtensionW
#include "include/PathCchAddExtension.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_EXTENSION
return S_OK;
}
/* Native-style Paths */
return S_FALSE;
}
#define DEFINE_UNICODE FALSE
#define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
#define PATH_CCH_ADD_EXTENSION NativePathCchAddExtensionA
#include "include/PathCchAddExtension.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_EXTENSION
HRESULT PathCchAddExtensionW(PWSTR pszPath, size_t cchPath, PCWSTR pszExt)
{
#ifdef _WIN32
LPTCH pDot;
BOOL bExtDot;
LPTCH pBackslash;
size_t pszExtLength;
size_t pszPathLength;
#define DEFINE_UNICODE TRUE
#define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
#define PATH_CCH_ADD_EXTENSION NativePathCchAddExtensionW
#include "include/PathCchAddExtension.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef PATH_CCH_ADD_EXTENSION
if (!pszPath)
return S_FALSE;
/*
* PathCchAppend
*/
if (!pszExt)
return S_FALSE;
/* Windows-style Paths */
pszExtLength = lstrlenW(pszExt);
pszPathLength = lstrlenW(pszPath);
bExtDot = (pszExt[0] == '.') ? TRUE : FALSE;
#define DEFINE_UNICODE FALSE
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
#define _PATH_SEPARATOR_STR PATH_BACKSLASH_STR
#define PATH_CCH_APPEND PathCchAppendA
#include "include/PathCchAppend.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef _PATH_SEPARATOR_STR
#undef PATH_CCH_APPEND
pDot = wcsrchr(pszPath, '.');
pBackslash = wcsrchr(pszPath, '\\');
#define DEFINE_UNICODE TRUE
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
#define _PATH_SEPARATOR_STR PATH_BACKSLASH_STR
#define PATH_CCH_APPEND PathCchAppendW
#include "include/PathCchAppend.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef _PATH_SEPARATOR_STR
#undef PATH_CCH_APPEND
if (pDot && pBackslash)
{
if (pDot > pBackslash)
return S_FALSE;
}
if (cchPath > pszPathLength + pszExtLength + ((bExtDot) ? 0 : 1))
{
if (bExtDot)
swprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, L"%s", pszExt);
else
swprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, L".%s", pszExt);
return S_OK;
}
#endif
return S_FALSE;
}
HRESULT PathCchAppendA(PSTR pszPath, size_t cchPath, PCSTR pszMore)
{
BOOL pathBackslash;
BOOL moreBackslash;
size_t pszMoreLength;
size_t pszPathLength;
if (!pszPath)
return S_FALSE;
if (!pszMore)
return S_FALSE;
pszMoreLength = lstrlenA(pszMore);
pszPathLength = lstrlenA(pszPath);
pathBackslash = (pszPath[pszPathLength - 1] == '\\') ? TRUE : FALSE;
moreBackslash = (pszMore[0] == '\\') ? TRUE : FALSE;
if (pathBackslash && moreBackslash)
{
if ((pszPathLength + pszMoreLength - 1) < cchPath)
{
sprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, "%s", &pszMore[1]);
return S_OK;
}
}
else if ((pathBackslash && !moreBackslash) || (!pathBackslash && moreBackslash))
{
if ((pszPathLength + pszMoreLength) < cchPath)
{
sprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, "%s", pszMore);
return S_OK;
}
}
else if (!pathBackslash && !moreBackslash)
{
if ((pszPathLength + pszMoreLength + 1) < cchPath)
{
sprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, "\\%s", pszMore);
return S_OK;
}
}
return S_FALSE;
}
HRESULT PathCchAppendW(PWSTR pszPath, size_t cchPath, PCWSTR pszMore)
{
#ifdef _WIN32
BOOL pathBackslash;
BOOL moreBackslash;
size_t pszMoreLength;
size_t pszPathLength;
if (!pszPath)
return S_FALSE;
if (!pszMore)
return S_FALSE;
pszMoreLength = lstrlenW(pszMore);
pszPathLength = lstrlenW(pszPath);
pathBackslash = (pszPath[pszPathLength - 1] == '\\') ? TRUE : FALSE;
moreBackslash = (pszMore[0] == '\\') ? TRUE : FALSE;
if (pathBackslash && moreBackslash)
{
if ((pszPathLength + pszMoreLength - 1) < cchPath)
{
swprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, L"%s", &pszMore[1]);
return S_OK;
}
}
else if ((pathBackslash && !moreBackslash) || (!pathBackslash && moreBackslash))
{
if ((pszPathLength + pszMoreLength) < cchPath)
{
swprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, L"%s", pszMore);
return S_OK;
}
}
else if (!pathBackslash && !moreBackslash)
{
if ((pszPathLength + pszMoreLength + 1) < cchPath)
{
swprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, L"\\%s", pszMore);
return S_OK;
}
}
#endif
return S_FALSE;
}
/*
* PathCchAppendEx
*/
HRESULT PathCchAppendExA(PSTR pszPath, size_t cchPath, PCSTR pszMore, unsigned long dwFlags)
{
@ -266,6 +291,10 @@ HRESULT PathCchAppendExW(PWSTR pszPath, size_t cchPath, PCWSTR pszMore, unsigned
return 0;
}
/*
* PathCchCanonicalize
*/
HRESULT PathCchCanonicalizeA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn)
{
return 0;
@ -276,6 +305,10 @@ HRESULT PathCchCanonicalizeW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPath
return 0;
}
/*
* PathCchCanonicalizeEx
*/
HRESULT PathCchCanonicalizeExA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn, unsigned long dwFlags)
{
return 0;
@ -286,6 +319,10 @@ HRESULT PathCchCanonicalizeExW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPa
return 0;
}
/*
* PathAllocCanonicalize
*/
HRESULT PathAllocCanonicalizeA(PCSTR pszPathIn, unsigned long dwFlags, PSTR* ppszPathOut)
{
return 0;
@ -296,6 +333,10 @@ HRESULT PathAllocCanonicalizeW(PCWSTR pszPathIn, unsigned long dwFlags, PWSTR* p
return 0;
}
/*
* PathCchCombine
*/
HRESULT PathCchCombineA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn, PCSTR pszMore)
{
return 0;
@ -306,6 +347,10 @@ HRESULT PathCchCombineW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPathIn, P
return 0;
}
/*
* PathCchCombineEx
*/
HRESULT PathCchCombineExA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn, PCSTR pszMore, unsigned long dwFlags)
{
return 0;
@ -316,127 +361,79 @@ HRESULT PathCchCombineExW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPathIn,
return 0;
}
HRESULT PathAllocCombineA(PCSTR pszPathIn, PCSTR pszMore, unsigned long dwFlags, PSTR* ppszPathOut)
{
PSTR pszPathOut;
BOOL backslashIn;
BOOL backslashMore;
int pszMoreLength;
int pszPathInLength;
int pszPathOutLength;
/*
* PathAllocCombine
*/
if (!pszPathIn)
return S_FALSE;
/* Windows-style Paths */
if (!pszMore)
return S_FALSE;
#define DEFINE_UNICODE FALSE
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
#define _PATH_SEPARATOR_STR PATH_BACKSLASH_STR
#define PATH_ALLOC_COMBINE PathAllocCombineA
#include "include/PathAllocCombine.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef _PATH_SEPARATOR_STR
#undef PATH_ALLOC_COMBINE
pszPathInLength = lstrlenA(pszPathIn);
pszMoreLength = lstrlenA(pszMore);
#define DEFINE_UNICODE TRUE
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
#define _PATH_SEPARATOR_STR PATH_BACKSLASH_STR
#define PATH_ALLOC_COMBINE PathAllocCombineW
#include "include/PathAllocCombine.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef _PATH_SEPARATOR_STR
#undef PATH_ALLOC_COMBINE
backslashIn = (pszPathIn[pszPathInLength - 1] == '\\') ? TRUE : FALSE;
backslashMore = (pszMore[0] == '\\') ? TRUE : FALSE;
/* Unix-style Paths */
if (backslashMore)
{
if ((pszPathIn[1] == ':') && (pszPathIn[2] == '\\'))
{
size_t sizeOfBuffer;
#define DEFINE_UNICODE FALSE
#define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
#define _PATH_SEPARATOR_STR PATH_SLASH_STR
#define PATH_ALLOC_COMBINE UnixPathAllocCombineA
#include "include/PathAllocCombine.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef _PATH_SEPARATOR_STR
#undef PATH_ALLOC_COMBINE
pszPathOutLength = 2 + pszMoreLength;
sizeOfBuffer = (pszPathOutLength + 1) * 2;
#define DEFINE_UNICODE TRUE
#define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
#define _PATH_SEPARATOR_STR PATH_SLASH_STR
#define PATH_ALLOC_COMBINE UnixPathAllocCombineW
#include "include/PathAllocCombine.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef _PATH_SEPARATOR_STR
#undef PATH_ALLOC_COMBINE
pszPathOut = (PSTR) HeapAlloc(GetProcessHeap(), 0, sizeOfBuffer * 2);
sprintf_s(pszPathOut, sizeOfBuffer, "%c:%s", pszPathIn[0], pszMore);
/* Native-style Paths */
*ppszPathOut = pszPathOut;
#define DEFINE_UNICODE FALSE
#define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
#define _PATH_SEPARATOR_STR PATH_SEPARATOR_STR
#define PATH_ALLOC_COMBINE NativePathAllocCombineA
#include "include/PathAllocCombine.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef _PATH_SEPARATOR_STR
#undef PATH_ALLOC_COMBINE
return S_OK;
}
}
else
{
size_t sizeOfBuffer;
#define DEFINE_UNICODE TRUE
#define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
#define _PATH_SEPARATOR_STR PATH_SEPARATOR_STR
#define PATH_ALLOC_COMBINE NativePathAllocCombineW
#include "include/PathAllocCombine.c"
#undef DEFINE_UNICODE
#undef _PATH_SEPARATOR_CHR
#undef _PATH_SEPARATOR_STR
#undef PATH_ALLOC_COMBINE
pszPathOutLength = pszPathInLength + pszMoreLength;
sizeOfBuffer = (pszPathOutLength + 1) * 2;
pszPathOut = (PSTR) HeapAlloc(GetProcessHeap(), 0, sizeOfBuffer * 2);
if (backslashIn)
sprintf_s(pszPathOut, sizeOfBuffer, "%s%s", pszPathIn, pszMore);
else
sprintf_s(pszPathOut, sizeOfBuffer, "%s\\%s", pszPathIn, pszMore);
*ppszPathOut = pszPathOut;
return S_OK;
}
return S_OK;
}
HRESULT PathAllocCombineW(PCWSTR pszPathIn, PCWSTR pszMore, unsigned long dwFlags, PWSTR* ppszPathOut)
{
#ifdef _WIN32
PWSTR pszPathOut;
BOOL backslashIn;
BOOL backslashMore;
int pszMoreLength;
int pszPathInLength;
int pszPathOutLength;
if (!pszPathIn)
return S_FALSE;
if (!pszMore)
return S_FALSE;
pszPathInLength = lstrlenW(pszPathIn);
pszMoreLength = lstrlenW(pszMore);
backslashIn = (pszPathIn[pszPathInLength - 1] == '\\') ? TRUE : FALSE;
backslashMore = (pszMore[0] == '\\') ? TRUE : FALSE;
if (backslashMore)
{
if ((pszPathIn[1] == ':') && (pszPathIn[2] == '\\'))
{
size_t sizeOfBuffer;
pszPathOutLength = 2 + pszMoreLength;
sizeOfBuffer = (pszPathOutLength + 1) * 2;
pszPathOut = (PWSTR) HeapAlloc(GetProcessHeap(), 0, sizeOfBuffer * 2);
swprintf_s(pszPathOut, sizeOfBuffer, L"%c:%s", pszPathIn[0], pszMore);
*ppszPathOut = pszPathOut;
return S_OK;
}
}
else
{
size_t sizeOfBuffer;
pszPathOutLength = pszPathInLength + pszMoreLength;
sizeOfBuffer = (pszPathOutLength + 1) * 2;
pszPathOut = (PWSTR) HeapAlloc(GetProcessHeap(), 0, sizeOfBuffer * 2);
if (backslashIn)
swprintf_s(pszPathOut, sizeOfBuffer, L"%s%s", pszPathIn, pszMore);
else
swprintf_s(pszPathOut, sizeOfBuffer, L"%s\\%s", pszPathIn, pszMore);
*ppszPathOut = pszPathOut;
return S_OK;
}
#endif
return S_OK;
}
/**
* PathCchFindExtension
*/
HRESULT PathCchFindExtensionA(PCSTR pszPath, size_t cchPath, PCSTR* ppszExt)
{
@ -448,6 +445,10 @@ HRESULT PathCchFindExtensionW(PCWSTR pszPath, size_t cchPath, PCWSTR* ppszExt)
return 0;
}
/**
* PathCchRenameExtension
*/
HRESULT PathCchRenameExtensionA(PSTR pszPath, size_t cchPath, PCSTR pszExt)
{
return 0;
@ -458,6 +459,10 @@ HRESULT PathCchRenameExtensionW(PWSTR pszPath, size_t cchPath, PCWSTR pszExt)
return 0;
}
/**
* PathCchRemoveExtension
*/
HRESULT PathCchRemoveExtensionA(PSTR pszPath, size_t cchPath)
{
return 0;
@ -468,6 +473,10 @@ HRESULT PathCchRemoveExtensionW(PWSTR pszPath, size_t cchPath)
return 0;
}
/**
* PathCchIsRoot
*/
BOOL PathCchIsRootA(PCSTR pszPath)
{
return 0;
@ -478,6 +487,10 @@ BOOL PathCchIsRootW(PCWSTR pszPath)
return 0;
}
/**
* PathIsUNCEx
*/
BOOL PathIsUNCExA(PCSTR pszPath, PCSTR* ppszServer)
{
if (!pszPath)
@ -506,6 +519,10 @@ BOOL PathIsUNCExW(PCWSTR pszPath, PCWSTR* ppszServer)
return FALSE;
}
/**
* PathCchSkipRoot
*/
HRESULT PathCchSkipRootA(PCSTR pszPath, PCSTR* ppszRootEnd)
{
return 0;
@ -516,6 +533,10 @@ HRESULT PathCchSkipRootW(PCWSTR pszPath, PCWSTR* ppszRootEnd)
return 0;
}
/**
* PathCchStripToRoot
*/
HRESULT PathCchStripToRootA(PSTR pszPath, size_t cchPath)
{
return 0;
@ -526,6 +547,10 @@ HRESULT PathCchStripToRootW(PWSTR pszPath, size_t cchPath)
return 0;
}
/**
* PathCchStripPrefix
*/
HRESULT PathCchStripPrefixA(PSTR pszPath, size_t cchPath)
{
BOOL hasPrefix;
@ -588,6 +613,10 @@ HRESULT PathCchStripPrefixW(PWSTR pszPath, size_t cchPath)
return S_FALSE;
}
/**
* PathCchRemoveFileSpec
*/
HRESULT PathCchRemoveFileSpecA(PSTR pszPath, size_t cchPath)
{
return 0;
@ -598,3 +627,260 @@ HRESULT PathCchRemoveFileSpecW(PWSTR pszPath, size_t cchPath)
return 0;
}
/*
* Path Portability Functions
*/
/**
* PathCchConvertStyle
*/
HRESULT PathCchConvertStyleA(PSTR pszPath, size_t cchPath, unsigned long dwFlags)
{
int index;
if (dwFlags & PATH_STYLE_WINDOWS)
{
for (index = 0; index < cchPath; index++)
{
if (pszPath[index] == PATH_SLASH_CHR)
pszPath[index] = PATH_BACKSLASH_CHR;
}
}
else if (dwFlags & PATH_STYLE_UNIX)
{
for (index = 0; index < cchPath; index++)
{
if (pszPath[index] == PATH_BACKSLASH_CHR)
pszPath[index] = PATH_SLASH_CHR;
}
}
else if (dwFlags & PATH_STYLE_NATIVE)
{
if (PATH_SEPARATOR_CHR == PATH_BACKSLASH_CHR)
{
/* Unix-style to Windows-style */
for (index = 0; index < cchPath; index++)
{
if (pszPath[index] == PATH_SLASH_CHR)
pszPath[index] = PATH_BACKSLASH_CHR;
}
}
else if (PATH_SEPARATOR_CHR == PATH_SLASH_CHR)
{
/* Windows-style to Unix-style */
for (index = 0; index < cchPath; index++)
{
if (pszPath[index] == PATH_BACKSLASH_CHR)
pszPath[index] = PATH_SLASH_CHR;
}
}
else
{
/* Unexpected error */
return S_FALSE;
}
}
else
{
/* Gangnam style? */
return S_FALSE;
}
return S_OK;
}
HRESULT PathCchConvertStyleW(PWSTR pszPath, size_t cchPath, unsigned long dwFlags)
{
int index;
if (dwFlags & PATH_STYLE_WINDOWS)
{
for (index = 0; index < cchPath; index++)
{
if (pszPath[index] == PATH_SLASH_CHR)
pszPath[index] = PATH_BACKSLASH_CHR;
}
}
else if (dwFlags & PATH_STYLE_UNIX)
{
for (index = 0; index < cchPath; index++)
{
if (pszPath[index] == PATH_BACKSLASH_CHR)
pszPath[index] = PATH_SLASH_CHR;
}
}
else if (dwFlags & PATH_STYLE_NATIVE)
{
if (PATH_SEPARATOR_CHR == PATH_BACKSLASH_CHR)
{
/* Unix-style to Windows-style */
for (index = 0; index < cchPath; index++)
{
if (pszPath[index] == PATH_SLASH_CHR)
pszPath[index] = PATH_BACKSLASH_CHR;
}
}
else if (PATH_SEPARATOR_CHR == PATH_SLASH_CHR)
{
/* Windows-style to Unix-style */
for (index = 0; index < cchPath; index++)
{
if (pszPath[index] == PATH_BACKSLASH_CHR)
pszPath[index] = PATH_SLASH_CHR;
}
}
else
{
/* Unexpected error */
return S_FALSE;
}
}
else
{
/* Gangnam style? */
return S_FALSE;
}
return S_OK;
}
/**
* PathGetSharedLibraryExtension
*/
static const CHAR SharedLibraryExtensionDllA[] = "dll";
static const CHAR SharedLibraryExtensionSoA[] = "so";
static const CHAR SharedLibraryExtensionDylibA[] = "dylib";
static const WCHAR SharedLibraryExtensionDllW[] = { 'd','l','l' };
static const WCHAR SharedLibraryExtensionSoW[] = { 's','o' };
static const WCHAR SharedLibraryExtensionDylibW[] = { 'd','y','l','i','b' };
static const CHAR SharedLibraryExtensionDotDllA[] = ".dll";
static const CHAR SharedLibraryExtensionDotSoA[] = ".so";
static const CHAR SharedLibraryExtensionDotDylibA[] = ".dylib";
static const WCHAR SharedLibraryExtensionDotDllW[] = { '.','d','l','l' };
static const WCHAR SharedLibraryExtensionDotSoW[] = { '.','s','o' };
static const WCHAR SharedLibraryExtensionDotDylibW[] = { '.','d','y','l','i','b' };
PCSTR PathGetSharedLibraryExtensionA(unsigned long dwFlags)
{
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT)
{
if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
{
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
return SharedLibraryExtensionDotDllA;
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
return SharedLibraryExtensionDotSoA;
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
return SharedLibraryExtensionDotDylibA;
}
else
{
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
return SharedLibraryExtensionDllA;
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
return SharedLibraryExtensionSoA;
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
return SharedLibraryExtensionDylibA;
}
}
if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
{
#ifdef _WIN32
return SharedLibraryExtensionDotDllA;
#elif __APPLE__
if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
return SharedLibraryExtensionDotSoA;
else
return SharedLibraryExtensionDotDylibA;
#else
return SharedLibraryExtensionDotSoA;
#endif
}
else
{
#ifdef _WIN32
return SharedLibraryExtensionDllA;
#elif __APPLE__
if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
return SharedLibraryExtensionSoA;
else
return SharedLibraryExtensionDylibA;
#else
return SharedLibraryExtensionSoA;
#endif
}
return NULL;
}
PCWSTR PathGetSharedLibraryExtensionW(unsigned long dwFlags)
{
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT)
{
if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
{
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
return SharedLibraryExtensionDotDllW;
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
return SharedLibraryExtensionDotSoW;
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
return SharedLibraryExtensionDotDylibW;
}
else
{
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
return SharedLibraryExtensionDllW;
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
return SharedLibraryExtensionSoW;
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
return SharedLibraryExtensionDylibW;
}
}
if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
{
#ifdef _WIN32
return SharedLibraryExtensionDotDllW;
#elif __APPLE__
if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
return SharedLibraryExtensionDotSoW;
else
return SharedLibraryExtensionDotDylibW;
#else
return SharedLibraryExtensionDotSoW;
#endif
}
else
{
#ifdef _WIN32
return SharedLibraryExtensionDllW;
#elif __APPLE__
if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
return SharedLibraryExtensionSoW;
else
return SharedLibraryExtensionDylibW;
#else
return SharedLibraryExtensionSoW;
#endif
}
return NULL;
}