1 /* 2 * Copyright 2012 Hans Leidekker for CodeWeavers 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #include "config.h" 20 21 #include <stdarg.h> 22 23 #define COBJMACROS 24 25 #include "windef.h" 26 #include "winbase.h" 27 #include "objbase.h" 28 29 #include "wincodecs_private.h" 30 31 #include "wine/debug.h" 32 33 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); 34 35 typedef struct ColorContext { 36 IWICColorContext IWICColorContext_iface; 37 LONG ref; 38 WICColorContextType type; 39 BYTE *profile; 40 UINT profile_len; 41 UINT exif_color_space; 42 } ColorContext; 43 44 static inline ColorContext *impl_from_IWICColorContext(IWICColorContext *iface) 45 { 46 return CONTAINING_RECORD(iface, ColorContext, IWICColorContext_iface); 47 } 48 49 static HRESULT WINAPI ColorContext_QueryInterface(IWICColorContext *iface, REFIID iid, 50 void **ppv) 51 { 52 ColorContext *This = impl_from_IWICColorContext(iface); 53 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 54 55 if (!ppv) return E_INVALIDARG; 56 57 if (IsEqualIID(&IID_IUnknown, iid) || 58 IsEqualIID(&IID_IWICColorContext, iid)) 59 { 60 *ppv = &This->IWICColorContext_iface; 61 } 62 else 63 { 64 *ppv = NULL; 65 return E_NOINTERFACE; 66 } 67 68 IUnknown_AddRef((IUnknown*)*ppv); 69 return S_OK; 70 } 71 72 static ULONG WINAPI ColorContext_AddRef(IWICColorContext *iface) 73 { 74 ColorContext *This = impl_from_IWICColorContext(iface); 75 ULONG ref = InterlockedIncrement(&This->ref); 76 77 TRACE("(%p) refcount=%u\n", iface, ref); 78 79 return ref; 80 } 81 82 static ULONG WINAPI ColorContext_Release(IWICColorContext *iface) 83 { 84 ColorContext *This = impl_from_IWICColorContext(iface); 85 ULONG ref = InterlockedDecrement(&This->ref); 86 87 TRACE("(%p) refcount=%u\n", iface, ref); 88 89 if (ref == 0) 90 { 91 HeapFree(GetProcessHeap(), 0, This->profile); 92 HeapFree(GetProcessHeap(), 0, This); 93 } 94 95 return ref; 96 } 97 98 static HRESULT load_profile(const WCHAR *filename, BYTE **profile, UINT *len) 99 { 100 HANDLE handle; 101 DWORD count; 102 LARGE_INTEGER size; 103 BOOL ret; 104 105 *len = 0; 106 *profile = NULL; 107 handle = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); 108 if (handle == INVALID_HANDLE_VALUE) return HRESULT_FROM_WIN32(GetLastError()); 109 110 if (!(GetFileSizeEx(handle, &size))) 111 { 112 CloseHandle(handle); 113 return HRESULT_FROM_WIN32(GetLastError()); 114 } 115 if (size.u.HighPart) 116 { 117 WARN("file too large\n"); 118 CloseHandle(handle); 119 return E_FAIL; 120 } 121 if (!(*profile = HeapAlloc(GetProcessHeap(), 0, size.u.LowPart))) 122 { 123 CloseHandle(handle); 124 return E_OUTOFMEMORY; 125 } 126 ret = ReadFile(handle, *profile, size.u.LowPart, &count, NULL); 127 CloseHandle(handle); 128 if (!ret) { 129 HeapFree (GetProcessHeap(),0,*profile); 130 *profile = NULL; 131 return HRESULT_FROM_WIN32(GetLastError()); 132 } 133 if (count != size.u.LowPart) { 134 HeapFree (GetProcessHeap(),0,*profile); 135 *profile = NULL; 136 return E_FAIL; 137 } 138 *len = count; 139 return S_OK; 140 } 141 142 static HRESULT WINAPI ColorContext_InitializeFromFilename(IWICColorContext *iface, 143 LPCWSTR wzFilename) 144 { 145 ColorContext *This = impl_from_IWICColorContext(iface); 146 BYTE *profile; 147 UINT len; 148 HRESULT hr; 149 TRACE("(%p,%s)\n", iface, debugstr_w(wzFilename)); 150 151 if (This->type != WICColorContextUninitialized && This->type != WICColorContextProfile) 152 return WINCODEC_ERR_WRONGSTATE; 153 154 if (!wzFilename) return E_INVALIDARG; 155 156 hr = load_profile(wzFilename, &profile, &len); 157 if (FAILED(hr)) return hr; 158 159 HeapFree(GetProcessHeap(), 0, This->profile); 160 This->profile = profile; 161 This->profile_len = len; 162 This->type = WICColorContextProfile; 163 164 return S_OK; 165 } 166 167 static HRESULT WINAPI ColorContext_InitializeFromMemory(IWICColorContext *iface, 168 const BYTE *pbBuffer, UINT cbBufferSize) 169 { 170 ColorContext *This = impl_from_IWICColorContext(iface); 171 BYTE *profile; 172 TRACE("(%p,%p,%u)\n", iface, pbBuffer, cbBufferSize); 173 174 if (This->type != WICColorContextUninitialized && This->type != WICColorContextProfile) 175 return WINCODEC_ERR_WRONGSTATE; 176 177 if (!(profile = HeapAlloc(GetProcessHeap(), 0, cbBufferSize))) return E_OUTOFMEMORY; 178 memcpy(profile, pbBuffer, cbBufferSize); 179 180 HeapFree(GetProcessHeap(), 0, This->profile); 181 This->profile = profile; 182 This->profile_len = cbBufferSize; 183 This->type = WICColorContextProfile; 184 185 return S_OK; 186 } 187 188 static HRESULT WINAPI ColorContext_InitializeFromExifColorSpace(IWICColorContext *iface, 189 UINT value) 190 { 191 ColorContext *This = impl_from_IWICColorContext(iface); 192 TRACE("(%p,%u)\n", iface, value); 193 194 if (This->type != WICColorContextUninitialized && This->type != WICColorContextExifColorSpace) 195 return WINCODEC_ERR_WRONGSTATE; 196 197 This->exif_color_space = value; 198 This->type = WICColorContextExifColorSpace; 199 200 return S_OK; 201 } 202 203 static HRESULT WINAPI ColorContext_GetType(IWICColorContext *iface, 204 WICColorContextType *pType) 205 { 206 ColorContext *This = impl_from_IWICColorContext(iface); 207 TRACE("(%p,%p)\n", iface, pType); 208 209 if (!pType) return E_INVALIDARG; 210 211 *pType = This->type; 212 return S_OK; 213 } 214 215 static HRESULT WINAPI ColorContext_GetProfileBytes(IWICColorContext *iface, 216 UINT cbBuffer, BYTE *pbBuffer, UINT *pcbActual) 217 { 218 ColorContext *This = impl_from_IWICColorContext(iface); 219 TRACE("(%p,%u,%p,%p)\n", iface, cbBuffer, pbBuffer, pcbActual); 220 221 if (This->type != WICColorContextProfile) 222 return WINCODEC_ERR_NOTINITIALIZED; 223 224 if (!pcbActual) return E_INVALIDARG; 225 226 if (cbBuffer >= This->profile_len && pbBuffer) 227 memcpy(pbBuffer, This->profile, This->profile_len); 228 229 *pcbActual = This->profile_len; 230 231 return S_OK; 232 } 233 234 static HRESULT WINAPI ColorContext_GetExifColorSpace(IWICColorContext *iface, 235 UINT *pValue) 236 { 237 ColorContext *This = impl_from_IWICColorContext(iface); 238 TRACE("(%p,%p)\n", iface, pValue); 239 240 if (!pValue) return E_INVALIDARG; 241 242 *pValue = This->exif_color_space; 243 return S_OK; 244 } 245 246 static const IWICColorContextVtbl ColorContext_Vtbl = { 247 ColorContext_QueryInterface, 248 ColorContext_AddRef, 249 ColorContext_Release, 250 ColorContext_InitializeFromFilename, 251 ColorContext_InitializeFromMemory, 252 ColorContext_InitializeFromExifColorSpace, 253 ColorContext_GetType, 254 ColorContext_GetProfileBytes, 255 ColorContext_GetExifColorSpace 256 }; 257 258 HRESULT ColorContext_Create(IWICColorContext **colorcontext) 259 { 260 ColorContext *This; 261 262 if (!colorcontext) return E_INVALIDARG; 263 264 This = HeapAlloc(GetProcessHeap(), 0, sizeof(ColorContext)); 265 if (!This) return E_OUTOFMEMORY; 266 267 This->IWICColorContext_iface.lpVtbl = &ColorContext_Vtbl; 268 This->ref = 1; 269 This->type = 0; 270 This->profile = NULL; 271 This->profile_len = 0; 272 This->exif_color_space = ~0u; 273 274 *colorcontext = &This->IWICColorContext_iface; 275 276 return S_OK; 277 } 278