@@ -13,9 +13,15 @@ void ConvertSelectedTextInActiveWindow(HKL hklSource, HKL hklTarget)
1313
1414 // store previous clipboard data and set clipboard to dummy string
1515 ClipboardData prevClipboardData;
16- StoreClipboardData (&prevClipboardData);
16+ if (!StoreClipboardData (&prevClipboardData))
17+ return ;
1718
18- SetClipboardText (dummy);
19+ if (!SetClipboardText (dummy))
20+ {
21+ // restore the original clipboard data
22+ RestoreClipboardData (&prevClipboardData);
23+ return ;
24+ }
1925
2026 // copy the selected text by simulating Ctrl-C
2127 SendKeyCombo (VK_CONTROL, ' C' , FALSE );
@@ -74,7 +80,6 @@ void ConvertSelectedTextInActiveWindow(HKL hklSource, HKL hklTarget)
7480
7581 // restore the original clipboard data
7682 RestoreClipboardData (&prevClipboardData);
77- FreeClipboardData (&prevClipboardData);
7883}
7984
8085// /////////////////////////////////////////////////////////////////////////////
@@ -194,97 +199,172 @@ HKL DetectLayoutFromString(const WCHAR* str, int* pmatches)
194199// You must call FreeAllClipboardData on `formats` when it's no longer needed.
195200BOOL StoreClipboardData (ClipboardData* formats)
196201{
197- if (OpenClipboard (NULL ))
202+ if (!OpenClipboard (NULL ))
203+ return FALSE ;
204+
205+ formats->count = CountClipboardFormats ();
206+ if (formats->count == 0 )
207+ {
208+ DWORD dwError = GetLastError ();
209+ CloseClipboard ();
210+ return dwError == ERROR_SUCCESS;
211+ }
212+
213+ formats->dataArray = (ClipboardFormat*)malloc (sizeof (ClipboardData) * formats->count );
214+ ZeroMemory (formats->dataArray , sizeof (ClipboardData) * formats->count );
215+ int i = 0 ;
216+
217+ UINT format = EnumClipboardFormats (0 );
218+ while (format)
198219 {
199- formats->count = CountClipboardFormats ();
200- formats->dataArray = (ClipboardFormat*)malloc (sizeof (ClipboardData) * formats->count );
201- ZeroMemory (formats->dataArray , sizeof (ClipboardData) * formats->count );
202- int i = 0 ;
203- UINT format = EnumClipboardFormats (0 );
204- while (format)
220+ if (i > formats->count - 1 )
221+ break ;
222+
223+ HANDLE dataHandle = GetClipboardData (format);
224+ if (!dataHandle)
225+ break ;
226+
227+ size_t size;
228+ if (!(GlobalFlags (dataHandle) & GMEM_DISCARDED))
205229 {
206- HANDLE dataHandle = GetClipboardData (format);
207- LPVOID source = GlobalLock (dataHandle);
208- size_t size = GlobalSize (dataHandle);
209- formats->dataArray [i].format = format;
210- formats->dataArray [i].dataHandle = GlobalAlloc (GHND, size);
211- LPVOID dest = GlobalLock (formats->dataArray [i].dataHandle );
212- CopyMemory (dest, source, size);
213- GlobalUnlock (formats->dataArray [i].dataHandle );
214- GlobalUnlock (dataHandle);
215-
216- // next format
217- format = EnumClipboardFormats (format);
218- i++;
230+ size = GlobalSize (dataHandle);
231+ if (size == 0 )
232+ break ;
219233 }
220- CloseClipboard ();
221- return TRUE ;
234+ else
235+ size = 0 ;
236+
237+ LPVOID source = GlobalLock (dataHandle);
238+ if (!source)
239+ break ;
240+
241+ BOOL bCopySucceeded = FALSE ;
242+
243+ formats->dataArray [i].format = format;
244+ formats->dataArray [i].dataHandle = GlobalAlloc (GHND, size);
245+ if (formats->dataArray [i].dataHandle )
246+ {
247+ if (size == 0 )
248+ {
249+ bCopySucceeded = TRUE ;
250+ }
251+ else
252+ {
253+ LPVOID dest = GlobalLock (formats->dataArray [i].dataHandle );
254+ if (dest)
255+ {
256+ CopyMemory (dest, source, size);
257+ GlobalUnlock (formats->dataArray [i].dataHandle );
258+ bCopySucceeded = TRUE ;
259+ }
260+ }
261+
262+ if (!bCopySucceeded)
263+ GlobalFree (formats->dataArray [i].dataHandle );
264+ }
265+
266+ GlobalUnlock (dataHandle);
267+
268+ if (!bCopySucceeded)
269+ break ;
270+
271+ i++;
272+
273+ // next format
274+ format = EnumClipboardFormats (format);
222275 }
223- return FALSE ;
224- }
225276
226- // /////////////////////////////////////////////////////////////////////////////
227- // Restores the data in the clipboard from `formats` that was generated by
228- // StoreClipboardData.
229- BOOL RestoreClipboardData (const ClipboardData* formats)
230- {
231- if (OpenClipboard (NULL ))
277+ CloseClipboard ();
278+
279+ if (format) // if failed before completion
232280 {
233- EmptyClipboard ();
234- for (int i = 0 ; i < formats->count ; i++)
281+ for (int j = 0 ; j < i; j++)
235282 {
236- SetClipboardData (formats->dataArray [i]. format , formats-> dataArray [i ].dataHandle );
283+ GlobalFree (formats->dataArray [j ].dataHandle );
237284 }
238- CloseClipboard ();
239- return TRUE ;
285+
286+ free (formats->dataArray );
287+ return FALSE ;
240288 }
241- return FALSE ;
289+
290+ return TRUE ;
242291}
243292
244293// /////////////////////////////////////////////////////////////////////////////
245- // Frees `formats` allocated by StoreClipboardData
246- void FreeClipboardData (ClipboardData* formats)
294+ // Restores the data in the clipboard from `formats` that was generated by
295+ // StoreClipboardData, and frees allocated data.
296+ BOOL RestoreClipboardData (ClipboardData* formats)
247297{
298+ if (!OpenClipboard (NULL ))
299+ return FALSE ;
300+
301+ EmptyClipboard ();
302+ for (int i = 0 ; i < formats->count ; i++)
303+ {
304+ SetClipboardData (formats->dataArray [i].format , formats->dataArray [i].dataHandle );
305+ }
306+
307+ CloseClipboard ();
248308 free (formats->dataArray );
309+ return TRUE ;
249310}
250311
251312// /////////////////////////////////////////////////////////////////////////////
252313// Gets unicode text from the clipboard.
253314// You must free the returned string when you don't need it anymore.
254315WCHAR* GetClipboardText ()
255316{
317+ if (!OpenClipboard (NULL ))
318+ return FALSE ;
319+
256320 WCHAR* text = NULL ;
257- if (OpenClipboard (NULL ))
321+ HANDLE handle = GetClipboardData (CF_UNICODETEXT);
322+ if (handle)
258323 {
259- HANDLE handle = GetClipboardData (CF_UNICODETEXT);
260324 WCHAR* clipboardText = (WCHAR*)GlobalLock (handle);
261- if (!clipboardText) return NULL ;
262- size_t size = sizeof (WCHAR) * (wcslen (clipboardText) + 1 );
263- text = (WCHAR*)malloc (size);
264- if (!text) return NULL ;
265- memcpy (text, clipboardText, size);
266- CloseClipboard ();
325+ if (clipboardText)
326+ {
327+ size_t size = sizeof (WCHAR) * (wcslen (clipboardText) + 1 );
328+ text = (WCHAR*)malloc (size);
329+ if (text)
330+ memcpy (text, clipboardText, size);
331+
332+ GlobalUnlock (handle);
333+ }
267334 }
335+
336+ CloseClipboard ();
268337 return text;
269338}
270339
271340// /////////////////////////////////////////////////////////////////////////////
272341// Puts unicode text on the clipboard
273342BOOL SetClipboardText (const WCHAR* text)
274343{
275- if (OpenClipboard (NULL ))
344+ if (!OpenClipboard (NULL ))
345+ return FALSE ;
346+
347+ BOOL bSucceeded = FALSE ;
348+
349+ size_t size = sizeof (WCHAR) * (wcslen (text) + 1 );
350+ HANDLE handle = GlobalAlloc (GHND, size);
351+ if (handle)
276352 {
277- size_t size = sizeof (WCHAR) * (wcslen (text) + 1 );
278- HANDLE handle = GlobalAlloc (GHND, size);
279353 WCHAR* clipboardText = (WCHAR*)GlobalLock (handle);
280- memcpy (clipboardText, text, size);
281- GlobalUnlock (handle);
282- EmptyClipboard ();
283- SetClipboardData (CF_UNICODETEXT, handle);
284- CloseClipboard ();
285- return TRUE ;
354+ if (clipboardText)
355+ {
356+ memcpy (clipboardText, text, size);
357+ GlobalUnlock (handle);
358+ bSucceeded = EmptyClipboard () &&
359+ SetClipboardData (CF_UNICODETEXT, handle);
360+ }
361+
362+ if (!bSucceeded)
363+ GlobalFree (handle);
286364 }
287- return FALSE ;
365+
366+ CloseClipboard ();
367+ return bSucceeded;
288368}
289369
290370// /////////////////////////////////////////////////////////////////////////////
0 commit comments