ReactOS  0.4.14-dev-606-g14ebc0b
custom.c
Go to the documentation of this file.
1 /*
2  * Custom Action processing for the Microsoft Installer (msi.dll)
3  *
4  * Copyright 2005 Aric Stewart for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include "config.h"
22 #include "wine/port.h"
23 
24 #define COBJMACROS
25 
26 #include <stdarg.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winerror.h"
30 #include "msidefs.h"
31 #include "winuser.h"
32 #include "objbase.h"
33 #include "oleauto.h"
34 
35 #include "msipriv.h"
36 #include "msiserver.h"
37 #include "wine/debug.h"
38 #include "wine/unicode.h"
39 #include "wine/exception.h"
40 
41 #ifdef _MSC_VER
42 #include "msvchelper.h"
43 #endif
44 
46 
47 #define CUSTOM_ACTION_TYPE_MASK 0x3F
48 
49 typedef struct tagMSIRUNNINGACTION
50 {
51  struct list entry;
56 
58 
61 {
62  0, 0, &msi_custom_action_cs,
65  0, 0, { (DWORD_PTR)(__FILE__ ": msi_custom_action_cs") }
66 };
68 
70 
72 {
73  UINT count;
74  WCHAR **newbuf = NULL;
75 
76  if (script >= SCRIPT_MAX)
77  {
78  FIXME("Unknown script requested %u\n", script);
79  return ERROR_FUNCTION_FAILED;
80  }
81  TRACE("Scheduling action %s in script %u\n", debugstr_w(action), script);
82 
83  count = package->script_actions_count[script];
84  package->script_actions_count[script]++;
85  if (count != 0) newbuf = msi_realloc( package->script_actions[script],
86  package->script_actions_count[script] * sizeof(WCHAR *) );
87  else newbuf = msi_alloc( sizeof(WCHAR *) );
88 
89  newbuf[count] = strdupW( action );
90  package->script_actions[script] = newbuf;
91  return ERROR_SUCCESS;
92 }
93 
95 {
96  UINT count;
97  WCHAR **newbuf = NULL;
98 
99  TRACE("Registering %s as unique action\n", debugstr_w(action));
100 
101  count = package->unique_actions_count;
102  package->unique_actions_count++;
103  if (count != 0) newbuf = msi_realloc( package->unique_actions,
104  package->unique_actions_count * sizeof(WCHAR *) );
105  else newbuf = msi_alloc( sizeof(WCHAR *) );
106 
107  newbuf[count] = strdupW( action );
108  package->unique_actions = newbuf;
109  return ERROR_SUCCESS;
110 }
111 
113 {
114  UINT i;
115 
116  for (i = 0; i < package->unique_actions_count; i++)
117  {
118  if (!strcmpW( package->unique_actions[i], action )) return TRUE;
119  }
120  return FALSE;
121 }
122 
124 {
127  {
128  if (!(package->InWhatSequence & SEQUENCE_UI &&
129  package->InWhatSequence & SEQUENCE_EXEC))
130  {
131  TRACE("Skipping action due to dbCustomActionTypeClientRepeat option.\n");
132  return FALSE;
133  }
134  }
136  {
137  if (package->InWhatSequence & SEQUENCE_UI &&
138  package->InWhatSequence & SEQUENCE_EXEC )
139  {
140  TRACE("Skipping action due to msidbCustomActionTypeFirstSequence option.\n");
141  return FALSE;
142  }
143  }
145  {
146  if (msi_action_is_unique(package, action))
147  {
148  TRACE("Skipping action due to msidbCustomActionTypeOncePerProcess option.\n");
149  return FALSE;
150  }
151  else
153  }
154 
155  return TRUE;
156 }
157 
158 /* stores the following properties before the action:
159  *
160  * [CustomActionData<=>UserSID<=>ProductCode]Action
161  */
163  LPCWSTR usersid, LPCWSTR prodcode)
164 {
165  LPWSTR deferred;
166  DWORD len;
167 
168  static const WCHAR format[] = {
169  '[','%','s','<','=','>','%','s','<','=','>','%','s',']','%','s',0
170  };
171 
172  if (!actiondata)
173  return strdupW(action);
174 
175  len = lstrlenW(action) + lstrlenW(actiondata) +
176  lstrlenW(usersid) + lstrlenW(prodcode) +
177  lstrlenW(format) - 7;
178  deferred = msi_alloc(len * sizeof(WCHAR));
179 
180  sprintfW(deferred, format, actiondata, usersid, prodcode, action);
181  return deferred;
182 }
183 
184 static void set_deferred_action_props( MSIPACKAGE *package, const WCHAR *deferred_data )
185 {
186  static const WCHAR sep[] = {'<','=','>',0};
187  const WCHAR *end, *beg = deferred_data + 1;
188 
189  end = strstrW(beg, sep);
190  msi_set_property( package->db, szCustomActionData, beg, end - beg );
191  beg = end + 3;
192 
193  end = strstrW(beg, sep);
194  msi_set_property( package->db, szUserSID, beg, end - beg );
195  beg = end + 3;
196 
197  end = strchrW(beg, ']');
198  msi_set_property( package->db, szProductCode, beg, end - beg );
199 }
200 
202 {
203  WCHAR *ret;
204 
205  if (!db->tempfolder)
206  {
207  WCHAR tmp[MAX_PATH];
208  UINT len = sizeof(tmp)/sizeof(tmp[0]);
209 
210  if (msi_get_property( db, szTempFolder, tmp, &len ) ||
212  {
213  GetTempPathW( MAX_PATH, tmp );
214  }
215  if (!(db->tempfolder = strdupW( tmp ))) return NULL;
216  }
217 
218  if ((ret = msi_alloc( (strlenW( db->tempfolder ) + 20) * sizeof(WCHAR) )))
219  {
220  if (!GetTempFileNameW( db->tempfolder, szMsi, 0, ret ))
221  {
222  msi_free( ret );
223  return NULL;
224  }
225  }
226 
227  return ret;
228 }
229 
231 {
232  static const WCHAR query[] = {
233  'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
234  '`','B','i' ,'n','a','r','y','`',' ','W','H','E','R','E',' ',
235  '`','N','a','m','e','`',' ','=',' ','\'','%','s','\'',0};
236  MSIRECORD *row;
237  MSIBINARY *binary = NULL;
238  HANDLE file;
239  CHAR buffer[1024];
240  WCHAR *tmpfile;
241  DWORD sz, write;
242  UINT r;
243 
244  if (!(tmpfile = msi_create_temp_file( package->db ))) return NULL;
245 
246  if (!(row = MSI_QueryGetRecord( package->db, query, source ))) goto error;
247  if (!(binary = msi_alloc_zero( sizeof(MSIBINARY) ))) goto error;
248 
250  if (file == INVALID_HANDLE_VALUE) goto error;
251 
252  do
253  {
254  sz = sizeof(buffer);
255  r = MSI_RecordReadStream( row, 2, buffer, &sz );
256  if (r != ERROR_SUCCESS)
257  {
258  ERR("Failed to get stream\n");
259  break;
260  }
261  WriteFile( file, buffer, sz, &write, NULL );
262  } while (sz == sizeof buffer);
263 
264  CloseHandle( file );
265  if (r != ERROR_SUCCESS) goto error;
266 
267  /* keep a reference to prevent the dll from being unloaded */
268  if (dll && !(binary->module = LoadLibraryW( tmpfile )))
269  {
270  ERR( "failed to load dll %s (%u)\n", debugstr_w( tmpfile ), GetLastError() );
271  }
272  binary->source = strdupW( source );
273  binary->tmpfile = tmpfile;
274  list_add_tail( &package->binaries, &binary->entry );
275 
276  msiobj_release( &row->hdr );
277  return binary;
278 
279 error:
280  if (row) msiobj_release( &row->hdr );
281  DeleteFileW( tmpfile );
282  msi_free( tmpfile );
283  msi_free( binary );
284  return NULL;
285 }
286 
288 {
289  MSIBINARY *binary;
290 
292  {
293  if (!strcmpW( binary->source, source ))
294  return binary;
295  }
296 
297  return create_temp_binary( package, source, dll );
298 }
299 
302 {
304 
305  action = msi_alloc( sizeof(MSIRUNNINGACTION) );
306 
307  action->handle = Handle;
308  action->process = process;
309  action->name = strdupW(name);
310 
311  list_add_tail( &package->RunningActions, &action->entry );
312 }
313 
315 {
316  DWORD rc = 0;
317 
318  GetExitCodeProcess( process, &rc );
319  TRACE("exit code is %u\n", rc);
320  if (rc != 0)
321  return ERROR_FUNCTION_FAILED;
322  return ERROR_SUCCESS;
323 }
324 
326 {
327  DWORD rc = 0;
328 
329  GetExitCodeThread( thread, &rc );
330 
331  switch (rc)
332  {
334  case ERROR_SUCCESS:
337  return rc;
338  case ERROR_NO_MORE_ITEMS:
339  return ERROR_SUCCESS;
341  ACTION_ForceReboot( package );
342  return ERROR_SUCCESS;
343  default:
344  ERR("Invalid Return Code %d\n",rc);
345  return ERROR_INSTALL_FAILURE;
346  }
347 }
348 
351 {
352  UINT rc = ERROR_SUCCESS;
353 
355  {
356  TRACE("waiting for %s\n", debugstr_w(name));
357 
359 
362 
364  }
365  else
366  {
367  TRACE("%s running in background\n", debugstr_w(name));
368 
371  else
373  }
374 
375  return rc;
376 }
377 
378 typedef struct _msi_custom_action_info {
379  struct list entry;
389 
391 {
393 
394  if (!--info->refs)
395  {
396  list_remove( &info->entry );
397  if (info->handle)
398  CloseHandle( info->handle );
399  msi_free( info->action );
400  msi_free( info->source );
401  msi_free( info->target );
402  msiobj_release( &info->package->hdr );
403  msi_free( info );
404  }
405 
407 }
408 
409 /* must be called inside msi_custom_action_cs if info is in the pending custom actions list */
411 {
412  info->refs++;
413  }
414 
416 {
417  UINT rc = ERROR_SUCCESS;
418 
419  if (!(info->type & msidbCustomActionTypeAsync))
420  {
421  TRACE("waiting for %s\n", debugstr_w( info->action ));
422 
423  msi_dialog_check_messages( info->handle );
424 
425  if (!(info->type & msidbCustomActionTypeContinue))
426  rc = custom_get_thread_return( info->package, info->handle );
427 
429  }
430  else
431  {
432  TRACE("%s running in background\n", debugstr_w( info->action ));
433  }
434 
435  return rc;
436 }
437 
439 {
441  BOOL found = FALSE;
442 
444 
446  {
447  if (IsEqualGUID( &info->guid, guid ))
448  {
450  found = TRUE;
451  break;
452  }
453  }
454 
456 
457  if (!found)
458  return NULL;
459 
460  return info;
461 }
462 
464 {
465  LPWSTR msg;
466  WCHAR val[MAX_PATH];
467 
468  static const WCHAR MsiBreak[] = { 'M','s','i','B','r','e','a','k',0 };
469  static const WCHAR WindowsInstaller[] = {
470  'W','i','n','d','o','w','s',' ','I','n','s','t','a','l','l','e','r',0
471  };
472 
473  static const WCHAR format[] = {
474  'T','o',' ','d','e','b','u','g',' ','y','o','u','r',' ',
475  'c','u','s','t','o','m',' ','a','c','t','i','o','n',',',' ',
476  'a','t','t','a','c','h',' ','y','o','u','r',' ','d','e','b','u','g','g','e','r',' ',
477  't','o',' ','p','r','o','c','e','s','s',' ','%','i',' ','(','0','x','%','X',')',' ',
478  'a','n','d',' ','p','r','e','s','s',' ','O','K',0
479  };
480 
481  if( !GetEnvironmentVariableW( MsiBreak, val, MAX_PATH ))
482  return;
483 
484  if( strcmpiW( val, target ))
485  return;
486 
487  msg = msi_alloc( (lstrlenW(format) + 10) * sizeof(WCHAR) );
488  if (!msg)
489  return;
490 
493  msi_free(msg);
494  DebugBreak();
495 }
496 
498  BSTR *dll, BSTR *funcname,
499  IWineMsiRemotePackage **package )
500 {
501  IClassFactory *cf = NULL;
503  HRESULT r;
504 
505  r = DllGetClassObject( &CLSID_WineMsiRemoteCustomAction,
506  &IID_IClassFactory, (LPVOID *)&cf );
507  if (FAILED(r))
508  {
509  ERR("failed to get IClassFactory interface\n");
510  return ERROR_FUNCTION_FAILED;
511  }
512 
513  r = IClassFactory_CreateInstance( cf, NULL, &IID_IWineMsiRemoteCustomAction, (LPVOID *)&rca );
514  if (FAILED(r))
515  {
516  ERR("failed to get IWineMsiRemoteCustomAction interface\n");
517  return ERROR_FUNCTION_FAILED;
518  }
519 
520  r = IWineMsiRemoteCustomAction_GetActionInfo( rca, guid, type, handle, dll, funcname, package );
521  IWineMsiRemoteCustomAction_Release( rca );
522  if (FAILED(r))
523  {
524  ERR("GetActionInfo failed\n");
525  return ERROR_FUNCTION_FAILED;
526  }
527 
528  return ERROR_SUCCESS;
529 }
530 
531 #ifdef __i386__
534  "pushl %ebp\n\t"
535  __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
536  __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
537  "movl %esp,%ebp\n\t"
538  __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
539  "subl $4,%esp\n\t"
540  "pushl 12(%ebp)\n\t"
541  "movl 8(%ebp),%eax\n\t"
542  "call *%eax\n\t"
543  "leave\n\t"
544  __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
545  __ASM_CFI(".cfi_same_value %ebp\n\t")
546  "ret" )
547 #else
549 {
550  return proc(handle);
551 }
552 #endif
553 
555 {
557  MSIHANDLE hPackage, handle;
558  HANDLE hModule;
559  LPSTR proc;
561  BSTR dll = NULL, function = NULL;
562  INT type;
563  IWineMsiRemotePackage *remote_package = NULL;
564 
565  TRACE("%s\n", debugstr_guid( guid ));
566 
567  r = get_action_info( guid, &type, &handle, &dll, &function, &remote_package );
568  if (r != ERROR_SUCCESS)
569  return r;
570 
571  hModule = LoadLibraryW( dll );
572  if (!hModule)
573  {
574  ERR( "failed to load dll %s (%u)\n", debugstr_w( dll ), GetLastError() );
575  return ERROR_SUCCESS;
576  }
577 
578  proc = strdupWtoA( function );
580  msi_free( proc );
581  if (fn)
582  {
583  hPackage = alloc_msi_remote_handle( (IUnknown *)remote_package );
584  if (hPackage)
585  {
586  IWineMsiRemotePackage_SetMsiHandle( remote_package, handle );
587  TRACE("calling %s\n", debugstr_w( function ) );
588  handle_msi_break( function );
589 
590  __TRY
591  {
592  r = CUSTOMPROC_wrapper( fn, hPackage );
593  }
595  {
596  ERR("Custom action (%s:%s) caused a page fault: %08x\n",
597  debugstr_w(dll), debugstr_w(function), GetExceptionCode());
598  r = ERROR_SUCCESS;
599  }
600  __ENDTRY;
601 
602  MsiCloseHandle( hPackage );
603  }
604  else
605  ERR("failed to create handle for %p\n", remote_package );
606  }
607  else
608  ERR("GetProcAddress(%s) failed\n", debugstr_w( function ) );
609 
611 
612  IWineMsiRemotePackage_Release( remote_package );
613  SysFreeString( dll );
614  SysFreeString( function );
616 
617  return r;
618 }
619 
621 {
622  LPGUID guid = arg;
623  DWORD rc = 0;
624 
625  TRACE("custom action (%x) started\n", GetCurrentThreadId() );
626 
628 
629  TRACE("custom action (%x) returned %i\n", GetCurrentThreadId(), rc );
630 
632  return rc;
633 }
634 
637 {
639 
640  info = msi_alloc( sizeof *info );
641  if (!info)
642  return NULL;
643 
644  msiobj_addref( &package->hdr );
645  info->refs = 2; /* 1 for our caller and 1 for thread we created */
646  info->package = package;
647  info->type = type;
648  info->target = strdupW( target );
649  info->source = strdupW( source );
650  info->action = strdupW( action );
651  CoCreateGuid( &info->guid );
652 
656 
657  info->handle = CreateThread( NULL, 0, DllThread, &info->guid, 0, NULL );
658  if (!info->handle)
659  {
660  /* release both references */
663  return NULL;
664  }
665 
666  return info;
667 }
668 
669 static UINT HANDLE_CustomType1( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
670  INT type, const WCHAR *action )
671 {
673  MSIBINARY *binary;
674 
675  if (!(binary = get_temp_binary( package, source, TRUE )))
676  return ERROR_FUNCTION_FAILED;
677 
678  TRACE("Calling function %s from %s\n", debugstr_w(target), debugstr_w(binary->tmpfile));
679 
680  info = do_msidbCustomActionTypeDll( package, type, binary->tmpfile, target, action );
681  return wait_thread_handle( info );
682 }
683 
684 static HANDLE execute_command( const WCHAR *app, WCHAR *arg, const WCHAR *dir )
685 {
686  static const WCHAR dotexeW[] = {'.','e','x','e',0};
687  STARTUPINFOW si;
689  WCHAR *exe = NULL, *cmd = NULL, *p;
690  BOOL ret;
691 
692  if (app)
693  {
694  int len_arg = 0;
695  DWORD len_exe;
696 
697  if (!(exe = msi_alloc( MAX_PATH * sizeof(WCHAR) ))) return INVALID_HANDLE_VALUE;
698  len_exe = SearchPathW( NULL, app, dotexeW, MAX_PATH, exe, NULL );
699  if (len_exe >= MAX_PATH)
700  {
701  msi_free( exe );
702  if (!(exe = msi_alloc( len_exe * sizeof(WCHAR) ))) return INVALID_HANDLE_VALUE;
703  len_exe = SearchPathW( NULL, app, dotexeW, len_exe, exe, NULL );
704  }
705  if (!len_exe)
706  {
707  ERR("can't find executable %u\n", GetLastError());
708  msi_free( exe );
709  return INVALID_HANDLE_VALUE;
710  }
711 
712  if (arg) len_arg = strlenW( arg );
713  if (!(cmd = msi_alloc( (len_exe + len_arg + 4) * sizeof(WCHAR) )))
714  {
715  msi_free( exe );
716  return INVALID_HANDLE_VALUE;
717  }
718  p = cmd;
719  if (strchrW( exe, ' ' ))
720  {
721  *p++ = '\"';
722  memcpy( p, exe, len_exe * sizeof(WCHAR) );
723  p += len_exe;
724  *p++ = '\"';
725  *p = 0;
726  }
727  else
728  {
729  strcpyW( p, exe );
730  p += len_exe;
731  }
732  if (arg)
733  {
734  *p++ = ' ';
735  memcpy( p, arg, len_arg * sizeof(WCHAR) );
736  p[len_arg] = 0;
737  }
738  }
739  memset( &si, 0, sizeof(STARTUPINFOW) );
740  ret = CreateProcessW( exe, exe ? cmd : arg, NULL, NULL, FALSE, 0, NULL, dir, &si, &info );
741  msi_free( cmd );
742  msi_free( exe );
743  if (!ret)
744  {
745  ERR("unable to execute command %u\n", GetLastError());
746  return INVALID_HANDLE_VALUE;
747  }
748  CloseHandle( info.hThread );
749  return info.hProcess;
750 }
751 
752 static UINT HANDLE_CustomType2( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
753  INT type, const WCHAR *action )
754 {
755  MSIBINARY *binary;
756  HANDLE handle;
757  WCHAR *arg;
758 
759  if (!(binary = get_temp_binary( package, source, FALSE ))) return ERROR_FUNCTION_FAILED;
760 
761  deformat_string( package, target, &arg );
762  TRACE("exe %s arg %s\n", debugstr_w(binary->tmpfile), debugstr_w(arg));
763 
764  handle = execute_command( binary->tmpfile, arg, szCRoot );
765  msi_free( arg );
767  return wait_process_handle( package, type, handle, action );
768 }
769 
770 static UINT HANDLE_CustomType17( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
771  INT type, const WCHAR *action )
772 {
774  MSIFILE *file;
775 
776  TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
777 
778  file = msi_get_loaded_file( package, source );
779  if (!file)
780  {
781  ERR("invalid file key %s\n", debugstr_w( source ));
782  return ERROR_FUNCTION_FAILED;
783  }
784 
785  info = do_msidbCustomActionTypeDll( package, type, file->TargetPath, target, action );
786  return wait_thread_handle( info );
787 }
788 
789 static UINT HANDLE_CustomType18( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
790  INT type, const WCHAR *action )
791 {
792  MSIFILE *file;
793  HANDLE handle;
794  WCHAR *arg;
795 
796  if (!(file = msi_get_loaded_file( package, source ))) return ERROR_FUNCTION_FAILED;
797 
798  deformat_string( package, target, &arg );
799  TRACE("exe %s arg %s\n", debugstr_w(file->TargetPath), debugstr_w(arg));
800 
801  handle = execute_command( file->TargetPath, arg, szCRoot );
802  msi_free( arg );
804  return wait_process_handle( package, type, handle, action );
805 }
806 
807 static UINT HANDLE_CustomType19( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
808  INT type, const WCHAR *action )
809 {
810  static const WCHAR query[] = {
811  'S','E','L','E','C','T',' ','`','M','e','s','s','a','g','e','`',' ',
812  'F','R','O','M',' ','`','E','r','r','o','r','`',' ',
813  'W','H','E','R','E',' ','`','E','r','r','o','r','`',' ','=',' ',
814  '%','s',0
815  };
816  MSIRECORD *row = 0;
817  LPWSTR deformated = NULL;
818 
819  deformat_string( package, target, &deformated );
820 
821  /* first try treat the error as a number */
822  row = MSI_QueryGetRecord( package->db, query, deformated );
823  if( row )
824  {
828  msiobj_release( &row->hdr );
829  }
830  else if ((package->ui_level & INSTALLUILEVEL_MASK) != INSTALLUILEVEL_NONE)
831  MessageBoxW( NULL, deformated, NULL, MB_OK );
832 
833  msi_free( deformated );
834 
835  return ERROR_INSTALL_FAILURE;
836 }
837 
838 static UINT HANDLE_CustomType23( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
839  INT type, const WCHAR *action )
840 {
841  static const WCHAR msiexecW[] = {'m','s','i','e','x','e','c',0};
842  static const WCHAR paramsW[] = {'/','q','b',' ','/','i',' '};
843  WCHAR *dir, *arg, *p;
844  UINT len_src, len_dir, len_tgt, len = sizeof(paramsW)/sizeof(paramsW[0]);
845  HANDLE handle;
846 
847  if (!(dir = msi_dup_property( package->db, szOriginalDatabase ))) return ERROR_OUTOFMEMORY;
848  if (!(p = strrchrW( dir, '\\' )) && !(p = strrchrW( dir, '/' )))
849  {
850  msi_free( dir );
851  return ERROR_FUNCTION_FAILED;
852  }
853  *p = 0;
854  len_dir = p - dir;
855  len_src = strlenW( source );
856  len_tgt = strlenW( target );
857  if (!(arg = msi_alloc( (len + len_dir + len_src + len_tgt + 5) * sizeof(WCHAR) )))
858  {
859  msi_free( dir );
860  return ERROR_OUTOFMEMORY;
861  }
862  memcpy( arg, paramsW, sizeof(paramsW) );
863  arg[len++] = '"';
864  memcpy( arg + len, dir, len_dir * sizeof(WCHAR) );
865  len += len_dir;
866  arg[len++] = '\\';
867  memcpy( arg + len, source, len_src * sizeof(WCHAR) );
868  len += len_src;
869  arg[len++] = '"';
870  arg[len++] = ' ';
871  strcpyW( arg + len, target );
872 
873  TRACE("installing %s concurrently\n", debugstr_w(source));
874 
875  handle = execute_command( msiexecW, arg, dir );
876  msi_free( dir );
877  msi_free( arg );
879  return wait_process_handle( package, type, handle, action );
880 }
881 
882 static UINT HANDLE_CustomType50( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
883  INT type, const WCHAR *action )
884 {
885  WCHAR *exe, *arg;
886  HANDLE handle;
887 
888  if (!(exe = msi_dup_property( package->db, source ))) return ERROR_SUCCESS;
889 
890  deformat_string( package, target, &arg );
891  TRACE("exe %s arg %s\n", debugstr_w(exe), debugstr_w(arg));
892 
893  handle = execute_command( exe, arg, szCRoot );
894  msi_free( exe );
895  msi_free( arg );
897  return wait_process_handle( package, type, handle, action );
898 }
899 
900 static UINT HANDLE_CustomType34( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
901  INT type, const WCHAR *action )
902 {
903  const WCHAR *workingdir = NULL;
904  HANDLE handle;
905  WCHAR *cmd;
906 
907  if (source)
908  {
909  workingdir = msi_get_target_folder( package, source );
910  if (!workingdir) return ERROR_FUNCTION_FAILED;
911  }
912  deformat_string( package, target, &cmd );
913  if (!cmd) return ERROR_FUNCTION_FAILED;
914 
915  TRACE("cmd %s dir %s\n", debugstr_w(cmd), debugstr_w(workingdir));
916 
917  handle = execute_command( NULL, cmd, workingdir );
918  msi_free( cmd );
920  return wait_process_handle( package, type, handle, action );
921 }
922 
924 {
926  MSIHANDLE hPackage;
928 
930  if (!info)
931  {
932  ERR("failed to find action %s\n", debugstr_guid( guid) );
933  return ERROR_FUNCTION_FAILED;
934  }
935 
936  TRACE("function %s, script %s\n", debugstr_w( info->target ), debugstr_w( info->source ) );
937 
938  hPackage = alloc_msihandle( &info->package->hdr );
939  if (hPackage)
940  {
941  r = call_script( hPackage, info->type, info->source, info->target, info->action );
942  TRACE("script returned %u\n", r);
943  MsiCloseHandle( hPackage );
944  }
945  else
946  ERR("failed to create handle for %p\n", info->package );
947 
949  return r;
950 }
951 
953 {
954  LPGUID guid = arg;
955  DWORD rc;
956 
957  TRACE("custom action (%x) started\n", GetCurrentThreadId() );
958 
959  rc = ACTION_CallScript( guid );
960 
961  TRACE("custom action (%x) returned %i\n", GetCurrentThreadId(), rc );
962 
964  return rc;
965 }
966 
968  MSIPACKAGE *package, INT type, LPCWSTR script, LPCWSTR function, LPCWSTR action )
969 {
971 
972  info = msi_alloc( sizeof *info );
973  if (!info)
974  return NULL;
975 
976  msiobj_addref( &package->hdr );
977  info->refs = 2; /* 1 for our caller and 1 for thread we created */
978  info->package = package;
979  info->type = type;
980  info->target = strdupW( function );
981  info->source = strdupW( script );
982  info->action = strdupW( action );
983  CoCreateGuid( &info->guid );
984 
988 
989  info->handle = CreateThread( NULL, 0, ScriptThread, &info->guid, 0, NULL );
990  if (!info->handle)
991  {
992  /* release both references */
995  return NULL;
996  }
997 
998  return info;
999 }
1000 
1001 static UINT HANDLE_CustomType37_38( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
1002  INT type, const WCHAR *action )
1003 {
1005 
1006  TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
1007 
1009  return wait_thread_handle( info );
1010 }
1011 
1012 static UINT HANDLE_CustomType5_6( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
1013  INT type, const WCHAR *action )
1014 {
1015  static const WCHAR query[] = {
1016  'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
1017  '`','B','i' ,'n','a','r','y','`',' ','W','H','E','R','E',' ',
1018  '`','N','a','m','e','`',' ','=',' ','\'','%','s','\'',0};
1019  MSIRECORD *row = NULL;
1021  CHAR *buffer = NULL;
1022  WCHAR *bufferw = NULL;
1023  DWORD sz = 0;
1024  UINT r;
1025 
1026  TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
1027 
1028  row = MSI_QueryGetRecord(package->db, query, source);
1029  if (!row)
1030  return ERROR_FUNCTION_FAILED;
1031 
1032  r = MSI_RecordReadStream(row, 2, NULL, &sz);
1033  if (r != ERROR_SUCCESS) goto done;
1034 
1035  buffer = msi_alloc( sz + 1 );
1036  if (!buffer)
1037  {
1039  goto done;
1040  }
1041 
1042  r = MSI_RecordReadStream(row, 2, buffer, &sz);
1043  if (r != ERROR_SUCCESS)
1044  goto done;
1045 
1046  buffer[sz] = 0;
1047  bufferw = strdupAtoW(buffer);
1048  if (!bufferw)
1049  {
1051  goto done;
1052  }
1053 
1054  info = do_msidbCustomActionTypeScript( package, type, bufferw, target, action );
1055  r = wait_thread_handle( info );
1056 
1057 done:
1058  msi_free(bufferw);
1059  msi_free(buffer);
1060  msiobj_release(&row->hdr);
1061  return r;
1062 }
1063 
1064 static UINT HANDLE_CustomType21_22( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
1065  INT type, const WCHAR *action )
1066 {
1068  MSIFILE *file;
1069  HANDLE hFile;
1070  DWORD sz, szHighWord = 0, read;
1071  CHAR *buffer=NULL;
1072  WCHAR *bufferw=NULL;
1073  BOOL bRet;
1074  UINT r;
1075 
1076  TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
1077 
1078  file = msi_get_loaded_file(package, source);
1079  if (!file)
1080  {
1081  ERR("invalid file key %s\n", debugstr_w(source));
1082  return ERROR_FUNCTION_FAILED;
1083  }
1084 
1087 
1088  sz = GetFileSize(hFile, &szHighWord);
1089  if (sz == INVALID_FILE_SIZE || szHighWord != 0)
1090  {
1091  CloseHandle(hFile);
1092  return ERROR_FUNCTION_FAILED;
1093  }
1094  buffer = msi_alloc( sz + 1 );
1095  if (!buffer)
1096  {
1097  CloseHandle(hFile);
1098  return ERROR_FUNCTION_FAILED;
1099  }
1100  bRet = ReadFile(hFile, buffer, sz, &read, NULL);
1101  CloseHandle(hFile);
1102  if (!bRet)
1103  {
1105  goto done;
1106  }
1107  buffer[read] = 0;
1108  bufferw = strdupAtoW(buffer);
1109  if (!bufferw)
1110  {
1112  goto done;
1113  }
1114  info = do_msidbCustomActionTypeScript( package, type, bufferw, target, action );
1115  r = wait_thread_handle( info );
1116 
1117 done:
1118  msi_free(bufferw);
1119  msi_free(buffer);
1120  return r;
1121 }
1122 
1123 static UINT HANDLE_CustomType53_54( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
1124  INT type, const WCHAR *action )
1125 {
1127  WCHAR *prop;
1128 
1129  TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
1130 
1131  prop = msi_dup_property( package->db, source );
1132  if (!prop) return ERROR_SUCCESS;
1133 
1134  info = do_msidbCustomActionTypeScript( package, type, prop, NULL, action );
1135  msi_free(prop);
1136  return wait_thread_handle( info );
1137 }
1138 
1140 {
1141  switch (script)
1142  {
1143  case SCRIPT_NONE:
1144  case SCRIPT_INSTALL:
1146  case SCRIPT_COMMIT:
1147  return (type & msidbCustomActionTypeCommit);
1148  case SCRIPT_ROLLBACK:
1150  default:
1151  ERR("unhandled script %u\n", script);
1152  }
1153  return FALSE;
1154 }
1155 
1157 {
1158  WCHAR *actiondata = msi_dup_property( package->db, action );
1159  WCHAR *usersid = msi_dup_property( package->db, szUserSID );
1160  WCHAR *prodcode = msi_dup_property( package->db, szProductCode );
1161  WCHAR *deferred = msi_get_deferred_action( action, actiondata, usersid, prodcode );
1162 
1163  if (!deferred)
1164  {
1165  msi_free( actiondata );
1166  msi_free( usersid );
1167  msi_free( prodcode );
1168  return ERROR_OUTOFMEMORY;
1169  }
1171  {
1172  TRACE("deferring commit action\n");
1173  msi_schedule_action( package, SCRIPT_COMMIT, deferred );
1174  }
1176  {
1177  TRACE("deferring rollback action\n");
1178  msi_schedule_action( package, SCRIPT_ROLLBACK, deferred );
1179  }
1180  else
1181  {
1182  TRACE("deferring install action\n");
1183  msi_schedule_action( package, SCRIPT_INSTALL, deferred );
1184  }
1185 
1186  msi_free( actiondata );
1187  msi_free( usersid );
1188  msi_free( prodcode );
1189  msi_free( deferred );
1190  return ERROR_SUCCESS;
1191 }
1192 
1194 {
1195  static const WCHAR query[] = {
1196  'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
1197  '`','C','u','s','t','o','m','A','c','t','i','o','n','`',' ','W','H','E','R','E',' ',
1198  '`','A','c','t','i' ,'o','n','`',' ','=',' ','\'','%','s','\'',0};
1199  UINT rc = ERROR_SUCCESS;
1200  MSIRECORD *row;
1201  UINT type;
1202  const WCHAR *source, *target, *ptr, *deferred_data = NULL;
1203  WCHAR *deformated = NULL;
1204  int len;
1205 
1206  /* deferred action: [properties]Action */
1207  if ((ptr = strrchrW(action, ']')))
1208  {
1209  deferred_data = action;
1210  action = ptr + 1;
1211  }
1212 
1213  row = MSI_QueryGetRecord( package->db, query, action );
1214  if (!row)
1216 
1220 
1221  TRACE("Handling custom action %s (%x %s %s)\n",debugstr_w(action),type,
1223 
1224  /* handle some of the deferred actions */
1226  FIXME("msidbCustomActionTypeTSAware not handled\n");
1227 
1229  {
1231  WARN("msidbCustomActionTypeNoImpersonate not handled\n");
1232 
1234  {
1235  rc = defer_custom_action( package, action, type );
1236  goto end;
1237  }
1238  else
1239  {
1240  LPWSTR actiondata = msi_dup_property( package->db, action );
1241 
1243  package->scheduled_action_running = TRUE;
1244 
1246  package->commit_action_running = TRUE;
1247 
1249  package->rollback_action_running = TRUE;
1250 
1251  if (deferred_data)
1252  set_deferred_action_props(package, deferred_data);
1253  else if (actiondata)
1254  msi_set_property( package->db, szCustomActionData, actiondata, -1 );
1255  else
1256  msi_set_property( package->db, szCustomActionData, szEmpty, -1 );
1257 
1258  msi_free(actiondata);
1259  }
1260  }
1261  else if (!check_execution_scheduling_options(package,action,type))
1262  {
1263  rc = ERROR_SUCCESS;
1264  goto end;
1265  }
1266 
1267  switch (type & CUSTOM_ACTION_TYPE_MASK)
1268  {
1269  case 1: /* DLL file stored in a Binary table stream */
1270  rc = HANDLE_CustomType1(package,source,target,type,action);
1271  break;
1272  case 2: /* EXE file stored in a Binary table stream */
1273  rc = HANDLE_CustomType2(package,source,target,type,action);
1274  break;
1275  case 18: /*EXE file installed with package */
1277  break;
1278  case 19: /* Error that halts install */
1280  break;
1281  case 17:
1283  break;
1284  case 23: /* installs another package in the source tree */
1285  deformat_string(package,target,&deformated);
1286  rc = HANDLE_CustomType23(package,source,deformated,type,action);
1287  msi_free(deformated);
1288  break;
1289  case 50: /*EXE file specified by a property value */
1291  break;
1292  case 34: /*EXE to be run in specified directory */
1294  break;
1295  case 35: /* Directory set with formatted text. */
1296  deformat_string(package,target,&deformated);
1297  MSI_SetTargetPathW(package, source, deformated);
1298  msi_free(deformated);
1299  break;
1300  case 51: /* Property set with formatted text. */
1301  if (!source)
1302  break;
1303 
1304  len = deformat_string( package, target, &deformated );
1305  rc = msi_set_property( package->db, source, deformated, len );
1306  if (rc == ERROR_SUCCESS && !strcmpW( source, szSourceDir ))
1307  msi_reset_folders( package, TRUE );
1308  msi_free(deformated);
1309  break;
1310  case 37: /* JScript/VBScript text stored in target column. */
1311  case 38:
1313  break;
1314  case 5:
1315  case 6: /* JScript/VBScript file stored in a Binary table stream. */
1317  break;
1318  case 21: /* JScript/VBScript file installed with the product. */
1319  case 22:
1321  break;
1322  case 53: /* JScript/VBScript text specified by a property value. */
1323  case 54:
1325  break;
1326  default:
1327  FIXME("unhandled action type %u (%s %s)\n", type & CUSTOM_ACTION_TYPE_MASK,
1329  }
1330 
1331 end:
1332  package->scheduled_action_running = FALSE;
1333  package->commit_action_running = FALSE;
1334  package->rollback_action_running = FALSE;
1335  msiobj_release(&row->hdr);
1336  return rc;
1337 }
1338 
1340 {
1341  struct list *item;
1342  HANDLE *wait_handles;
1343  unsigned int handle_count, i;
1345 
1346  while ((item = list_head( &package->RunningActions )))
1347  {
1349 
1350  list_remove( &action->entry );
1351 
1352  TRACE("waiting for %s\n", debugstr_w( action->name ) );
1353  msi_dialog_check_messages( action->handle );
1354 
1355  CloseHandle( action->handle );
1356  msi_free( action->name );
1357  msi_free( action );
1358  }
1359 
1361 
1362  handle_count = list_count( &msi_pending_custom_actions );
1363  wait_handles = msi_alloc( handle_count * sizeof(HANDLE) );
1364 
1365  handle_count = 0;
1367  {
1368  if (info->package == package )
1369  {
1370  if (DuplicateHandle(GetCurrentProcess(), info->handle, GetCurrentProcess(), &wait_handles[handle_count], SYNCHRONIZE, FALSE, 0))
1371  handle_count++;
1372  }
1373  }
1374 
1376 
1377  for (i = 0; i < handle_count; i++)
1378  {
1379  msi_dialog_check_messages( wait_handles[i] );
1380  CloseHandle( wait_handles[i] );
1381  }
1382  msi_free( wait_handles );
1383 
1386  {
1387  if (info->package == package) release_custom_action_data( info );
1388  }
1390 }
1391 
1392 typedef struct _msi_custom_remote_impl {
1396 
1398 {
1399  return CONTAINING_RECORD(iface, msi_custom_remote_impl, IWineMsiRemoteCustomAction_iface);
1400 }
1401 
1403  REFIID riid,LPVOID *ppobj)
1404 {
1405  if( IsEqualCLSID( riid, &IID_IUnknown ) ||
1406  IsEqualCLSID( riid, &IID_IWineMsiRemoteCustomAction ) )
1407  {
1408  IWineMsiRemoteCustomAction_AddRef( iface );
1409  *ppobj = iface;
1410  return S_OK;
1411  }
1412 
1413  return E_NOINTERFACE;
1414 }
1415 
1417 {
1419 
1420  return InterlockedIncrement( &This->refs );
1421 }
1422 
1424 {
1426  ULONG r;
1427 
1428  r = InterlockedDecrement( &This->refs );
1429  if (r == 0)
1430  msi_free( This );
1431  return r;
1432 }
1433 
1435  INT *type, MSIHANDLE *handle, BSTR *dll, BSTR *func, IWineMsiRemotePackage **remote_package )
1436 {
1438 
1439  info = find_action_by_guid( custom_action_guid );
1440  if (!info)
1441  return E_FAIL;
1442 
1443  *type = info->type;
1444  *handle = alloc_msihandle( &info->package->hdr );
1445  *dll = SysAllocString( info->source );
1446  *func = SysAllocString( info->target );
1447 
1449  return create_msi_remote_package( NULL, (LPVOID *)remote_package );
1450 }
1451 
1452 static const IWineMsiRemoteCustomActionVtbl msi_custom_remote_vtbl =
1453 {
1455  mcr_AddRef,
1456  mcr_Release,
1458 };
1459 
1461 {
1463 
1464  This = msi_alloc( sizeof *This );
1465  if (!This)
1466  return E_OUTOFMEMORY;
1467 
1468  This->IWineMsiRemoteCustomAction_iface.lpVtbl = &msi_custom_remote_vtbl;
1469  This->refs = 1;
1470 
1471  *ppObj = &This->IWineMsiRemoteCustomAction_iface;
1472 
1473  return S_OK;
1474 }
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
void msiobj_addref(MSIOBJECTHDR *info)
Definition: handle.c:218
LPWSTR tempfolder
Definition: msipriv.h:103
static UINT HANDLE_CustomType17(MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, INT type, const WCHAR *action)
Definition: custom.c:770
GLenum func
Definition: glext.h:6028
static BOOL check_execution_scheduling_options(MSIPACKAGE *package, LPCWSTR action, UINT options)
Definition: custom.c:123
UINT msi_get_property(MSIDATABASE *, LPCWSTR, LPWSTR, LPDWORD) DECLSPEC_HIDDEN
Definition: package.c:2336
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
void ACTION_FinishCustomActions(const MSIPACKAGE *package)
Definition: custom.c:1339
static UINT CUSTOMPROC_wrapper(MsiCustomActionEntryPoint proc, MSIHANDLE handle)
Definition: custom.c:548
static UINT HANDLE_CustomType18(MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, INT type, const WCHAR *action)
Definition: custom.c:789
#define CUSTOM_ACTION_TYPE_MASK
Definition: custom.c:47
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
UINT WINAPI MsiCloseAllHandles(void)
Definition: handle.c:326
static UINT custom_get_process_return(HANDLE process)
Definition: custom.c:314
#define CloseHandle
Definition: compat.h:406
#define E_NOINTERFACE
Definition: winerror.h:2364
static void handle_msi_break(LPCWSTR target)
Definition: custom.c:463
HRESULT create_msi_remote_package(IUnknown *pOuter, LPVOID *ppObj) DECLSPEC_HIDDEN
Definition: package.c:2783
static const WCHAR szUserSID[]
Definition: msipriv.h:1126
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
#define ERROR_SUCCESS
Definition: deptool.c:10
#define DWORD_PTR
Definition: treelist.c:76
#define error(str)
Definition: mkdosfs.c:1605
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:95
UINT ACTION_ForceReboot(MSIPACKAGE *package)
Definition: action.c:5407
static UINT HANDLE_CustomType53_54(MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, INT type, const WCHAR *action)
Definition: custom.c:1123
static DWORD WINAPI DllThread(LPVOID arg)
Definition: custom.c:620
Definition: ftp_var.h:139
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
MSIOBJECTHDR hdr
Definition: msipriv.h:385
static WCHAR * strdupW(const WCHAR *src)
Definition: main.c:92
REFIID riid
Definition: precomp.h:44
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
WINE_UNICODE_INLINE WCHAR * strchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:248
BOOL WINAPI GetExitCodeProcess(IN HANDLE hProcess, IN LPDWORD lpExitCode)
Definition: proc.c:1168
struct list RunningActions
Definition: msipriv.h:422
GLuint GLuint GLsizei count
Definition: gl.h:1545
LPWSTR * unique_actions
Definition: msipriv.h:417
char CHAR
Definition: xmlstorage.h:175
#define WARN(fmt,...)
Definition: debug.h:111
BOOL msi_action_is_unique(const MSIPACKAGE *package, const WCHAR *action)
Definition: custom.c:112
static LPSTR strdupWtoA(LPCWSTR str)
Definition: hhctrl.h:296
static ULONG WINAPI mcr_AddRef(IWineMsiRemoteCustomAction *iface)
Definition: custom.c:1416
static HANDLE process
Definition: process.c:76
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define INVALID_HANDLE_VALUE
Definition: compat.h:399
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
GLuint buffer
Definition: glext.h:5915
char * cmd
Definition: vfdcmd.c:85
void * arg
Definition: msvc.h:10
GLuint GLuint end
Definition: gl.h:1545
static HANDLE proc()
Definition: pdb.c:32
#define INVALID_FILE_SIZE
Definition: winbase.h:529
OLECHAR * BSTR
Definition: compat.h:1942
static UINT HANDLE_CustomType1(MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, INT type, const WCHAR *action)
Definition: custom.c:669
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
char * LPSTR
Definition: xmlstorage.h:182
#define lstrlenW
Definition: compat.h:415
#define E_FAIL
Definition: ddrawi.h:102
int32_t INT
Definition: typedefs.h:56
static void * msi_realloc(void *mem, size_t len) __WINE_ALLOC_SIZE(2)
Definition: msipriv.h:1216
unsigned long MSIHANDLE
Definition: msiserver.idl:25
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
static UINT HANDLE_CustomType19(MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, INT type, const WCHAR *action)
Definition: custom.c:807
#define FILE_SHARE_READ
Definition: compat.h:125
static void * msi_alloc_zero(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1210
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
Definition: shsvcs.c:38
UINT(WINAPI * MsiCustomActionEntryPoint)(MSIHANDLE)
Definition: custom.c:57
__WINE_SERVER_LIST_INLINE struct list * list_head(const struct list *list)
Definition: list.h:131
struct _test_info info[]
Definition: SetCursorPos.c:19
struct list entry
Definition: custom.c:51
static MSIBINARY * get_temp_binary(MSIPACKAGE *package, LPCWSTR source, BOOL dll)
Definition: custom.c:287
#define __ASM_GLOBAL_FUNC(name, code)
Definition: port.h:201
static HMODULE dll
Definition: str.c:188
BOOL WINAPI GetExitCodeThread(IN HANDLE hThread, OUT LPDWORD lpExitCode)
Definition: thread.c:540
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
#define write
Definition: acwin.h:97
static DWORD ACTION_CallDllFunction(const GUID *guid)
Definition: custom.c:554
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
const GUID * guid
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985
WINE_DEFAULT_DEBUG_CHANNEL(msi)
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
DWORD WINAPI GetTempPathW(IN DWORD count, OUT LPWSTR path)
Definition: path.c:2079
static UINT HANDLE_CustomType34(MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, INT type, const WCHAR *action)
Definition: custom.c:900
unsigned int BOOL
Definition: ntddk_ex.h:94
__WINE_SERVER_LIST_INLINE unsigned int list_count(const struct list *list)
Definition: list.h:155
long LONG
Definition: pedump.c:60
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:802
#define GENERIC_WRITE
Definition: nt_native.h:90
#define debugstr_w
Definition: kernel32.h:32
#define FIXME(fmt,...)
Definition: debug.h:110
static UINT wait_process_handle(MSIPACKAGE *package, UINT type, HANDLE ProcessHandle, LPCWSTR name)
Definition: custom.c:349
static PVOID ptr
Definition: dispmode.c:27
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
struct _msi_custom_action_info msi_custom_action_info
void WINAPI DebugBreak(void)
unsigned char rollback_action_running
Definition: msipriv.h:446
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:136
#define strstrW(d, s)
Definition: unicode.h:32
#define ERROR_FUNCTION_NOT_CALLED
Definition: winerror.h:984
#define LoadLibraryW(x)
Definition: compat.h:412
smooth NULL
Definition: ftsmooth.c:416
static HRESULT WINAPI mcr_QueryInterface(IWineMsiRemoteCustomAction *iface, REFIID riid, LPVOID *ppobj)
Definition: custom.c:1402
struct list binaries
Definition: msipriv.h:398
void msi_reset_folders(MSIPACKAGE *package, BOOL source) DECLSPEC_HIDDEN
Definition: package.c:2130
static msi_custom_action_info * do_msidbCustomActionTypeDll(MSIPACKAGE *package, INT type, LPCWSTR source, LPCWSTR target, LPCWSTR action)
Definition: custom.c:635
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:238
static void addref_custom_action_data(msi_custom_action_info *info)
Definition: custom.c:410
script
Definition: msipriv.h:374
MSIHANDLE alloc_msi_remote_handle(IUnknown *unk)
Definition: handle.c:133
const WCHAR * MSI_RecordGetString(const MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:482
unsigned int dir
Definition: maze.c:112
#define __TRY
Definition: compat.h:70
static void set_deferred_action_props(MSIPACKAGE *package, const WCHAR *deferred_data)
Definition: custom.c:184
DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function, LPCWSTR action) DECLSPEC_HIDDEN
Definition: script.c:293
static UINT HANDLE_CustomType50(MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, INT type, const WCHAR *action)
Definition: custom.c:882
#define debugstr_guid
Definition: kernel32.h:35
#define SEQUENCE_EXEC
Definition: msipriv.h:696
#define OPEN_EXISTING
Definition: compat.h:434
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
DWORD WINAPI GetCurrentThreadId(VOID)
Definition: thread.c:458
struct tagMSIRUNNINGACTION MSIRUNNINGACTION
#define ERROR_INSTALL_USEREXIT
Definition: winerror.h:960
#define __ASM_CFI(str)
Definition: asm.h:39
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4593
GLuint GLfloat * val
Definition: glext.h:7180
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
unsigned char commit_action_running
Definition: msipriv.h:445
_Check_return_ _CRTIMP FILE *__cdecl tmpfile(void)
Definition: file.c:3912
MSIFILE * msi_get_loaded_file(MSIPACKAGE *package, const WCHAR *key)
Definition: action.c:674
static const WCHAR szEmpty[]
Definition: provider.c:50
HRESULT create_msi_custom_remote(IUnknown *pOuter, LPVOID *ppObj)
Definition: custom.c:1460
#define GetExceptionCode()
Definition: exception.h:66
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
_In_ HANDLE Handle
Definition: extypes.h:390
DWORD deformat_string(MSIPACKAGE *package, const WCHAR *fmt, WCHAR **data)
Definition: format.c:1016
#define TRACE(s)
Definition: solgame.cpp:4
#define FreeLibrary(x)
Definition: compat.h:413
static void file_running_action(MSIPACKAGE *package, HANDLE Handle, BOOL process, LPCWSTR name)
Definition: custom.c:300
static const WCHAR szProductCode[]
Definition: msipriv.h:1127
LPWSTR * script_actions[SCRIPT_MAX]
Definition: msipriv.h:415
UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolderPath)
Definition: install.c:567
int WINAPI MessageBoxW(_In_opt_ HWND, _In_opt_ LPCWSTR, _In_opt_ LPCWSTR, _In_ UINT)
#define LIST_INIT(head)
Definition: queue.h:197
__wchar_t WCHAR
Definition: xmlstorage.h:180
MSIRECORD * MSI_QueryGetRecord(MSIDATABASE *db, LPCWSTR query,...) DECLSPEC_HIDDEN
Definition: msiquery.c:206
LONG HRESULT
Definition: typedefs.h:77
INSTALLUILEVEL ui_level
Definition: msipriv.h:430
const GUID IID_IUnknown
#define funcname
Definition: shellext.h:96
HANDLE WINAPI GetCurrentProcess(VOID)
Definition: proc.c:1138
#define ERROR_INSTALL_FAILURE
Definition: winerror.h:961
#define MAX_PATH
Definition: compat.h:26
#define WINAPI
Definition: msvc.h:6
const char file[]
Definition: icontest.c:11
UINT WINAPI GetTempFileNameW(IN LPCWSTR lpPathName, IN LPCWSTR lpPrefixString, IN UINT uUnique, OUT LPWSTR lpTempFileName)
Definition: filename.c:84
unsigned long DWORD
Definition: ntddk_ex.h:95
static CRITICAL_SECTION msi_custom_action_cs
Definition: custom.c:59
MSIDATABASE * db
Definition: msipriv.h:386
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:481
const GLuint GLenum const GLvoid * binary
Definition: glext.h:7538
int unique_actions_count
Definition: msipriv.h:418
static const WCHAR szMsi[]
Definition: msipriv.h:1119
struct list entry
Definition: custom.c:379
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:242
static UINT HANDLE_CustomType2(MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, INT type, const WCHAR *action)
Definition: custom.c:752
static DWORD WINAPI ScriptThread(LPVOID arg)
Definition: custom.c:952
HRESULT WINAPI CoCreateGuid(GUID *pguid)
Definition: compobj.c:2206
static HANDLE thread
Definition: service.c:33
static const WCHAR szSourceDir[]
Definition: msipriv.h:1100
#define __ENDTRY
Definition: compat.h:72
int ret
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
static const IWineMsiRemoteCustomActionVtbl msi_custom_remote_vtbl
Definition: custom.c:1452
#define InterlockedDecrement
Definition: armddk.h:52
static UINT defer_custom_action(MSIPACKAGE *package, const WCHAR *action, UINT type)
Definition: custom.c:1156
static UINT HANDLE_CustomType5_6(MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, INT type, const WCHAR *action)
Definition: custom.c:1012
#define INSTALLUILEVEL_MASK
Definition: msipriv.h:57
uint32_t entry
Definition: isohybrid.c:63
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
Definition: _list.h:228
#define GENERIC_READ
Definition: compat.h:124
static LPWSTR msi_get_deferred_action(LPCWSTR action, LPCWSTR actiondata, LPCWSTR usersid, LPCWSTR prodcode)
Definition: custom.c:162
#define SYNCHRONIZE
Definition: nt_native.h:61
LIST_ENTRY ProcessLocksList
Definition: winbase.h:855
_In_ HANDLE hFile
Definition: mswsock.h:90
unsigned char scheduled_action_running
Definition: msipriv.h:444
static UINT HANDLE_CustomType23(MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, INT type, const WCHAR *action)
Definition: custom.c:838
static UINT get_action_info(const GUID *guid, INT *type, MSIHANDLE *handle, BSTR *dll, BSTR *funcname, IWineMsiRemotePackage **package)
Definition: custom.c:497
UINT WINAPI MsiCloseHandle(MSIHANDLE handle)
Definition: handle.c:270
UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script)
Definition: custom.c:1193
DWORD WINAPI SearchPathW(IN LPCWSTR lpPath OPTIONAL, IN LPCWSTR lpFileName, IN LPCWSTR lpExtension OPTIONAL, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart OPTIONAL)
Definition: path.c:1297
#define strcmpiW(s1, s2)
Definition: unicode.h:39
WINE_UNICODE_INLINE WCHAR * strrchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:254
const WCHAR * msi_get_target_folder(MSIPACKAGE *package, const WCHAR *name)
Definition: install.c:209
int MSI_RecordGetInteger(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:245
#define ERR(fmt,...)
Definition: debug.h:109
static UINT custom_get_thread_return(MSIPACKAGE *package, HANDLE thread)
Definition: custom.c:325
static UINT wait_thread_handle(msi_custom_action_info *info)
Definition: custom.c:415
#define ERROR_INSTALL_SUSPEND
Definition: winerror.h:962
#define S_OK
Definition: intsafe.h:59
WINE_UNICODE_INLINE WCHAR * strcpyW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:219
static HANDLE execute_command(const WCHAR *app, WCHAR *arg, const WCHAR *dir)
Definition: custom.c:684
UINT InWhatSequence
Definition: msipriv.h:420
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:204
const WCHAR * action
Definition: action.c:7783
#define InterlockedIncrement
Definition: armddk.h:53
static ATOM item
Definition: dde.c:856
int script_actions_count[SCRIPT_MAX]
Definition: msipriv.h:416
static const WCHAR szTempFolder[]
Definition: msipriv.h:1182
const char cursor[]
Definition: icontest.c:13
static const WCHAR szOriginalDatabase[]
Definition: msipriv.h:1169
MSIPACKAGE * package
Definition: custom.c:381
GLsizei GLsizei GLchar * source
Definition: glext.h:6048
#define sprintfW
Definition: unicode.h:58
static struct list msi_pending_custom_actions
Definition: custom.c:69
IWineMsiRemoteCustomAction IWineMsiRemoteCustomAction_iface
Definition: custom.c:1393
static ULONG WINAPI mcr_Release(IWineMsiRemoteCustomAction *iface)
Definition: custom.c:1423
MSIHANDLE alloc_msihandle(MSIOBJECTHDR *obj)
Definition: handle.c:109
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271
unsigned int UINT
Definition: ndis.h:50
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
#define MB_OK
Definition: winuser.h:784
UINT msi_set_property(MSIDATABASE *, const WCHAR *, const WCHAR *, int) DECLSPEC_HIDDEN
Definition: package.c:2149
static MSIBINARY * create_temp_binary(MSIPACKAGE *package, LPCWSTR source, BOOL dll)
Definition: custom.c:230
#define CreateFileW
Definition: compat.h:408
static msi_custom_action_info * find_action_by_guid(const GUID *guid)
Definition: custom.c:438
UINT MSI_RecordReadStream(MSIRECORD *, UINT, char *, LPDWORD) DECLSPEC_HIDDEN
Definition: record.c:814
static const WCHAR szCRoot[]
Definition: msipriv.h:1184
#define msg(x)
Definition: auth_time.c:54
static BOOL msi_free(void *mem)
Definition: msipriv.h:1227
WCHAR * msi_create_temp_file(MSIDATABASE *db)
Definition: custom.c:201
static BOOL action_type_matches_script(UINT type, UINT script)
Definition: custom.c:1139
Definition: name.c:38
WINE_UNICODE_INLINE int strcmpW(const WCHAR *str1, const WCHAR *str2)
Definition: unicode.h:229
static void * msi_alloc(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1204
unsigned int ULONG
Definition: retypes.h:1
GLenum target
Definition: glext.h:7315
static UINT HANDLE_CustomType21_22(MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, INT type, const WCHAR *action)
Definition: custom.c:1064
#define GetProcAddress(x, y)
Definition: compat.h:418
static UINT HANDLE_CustomType37_38(MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, INT type, const WCHAR *action)
Definition: custom.c:1001
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
struct _msi_custom_remote_impl msi_custom_remote_impl
GLfloat GLfloat p
Definition: glext.h:8902
static HRESULT WINAPI mcr_GetActionInfo(IWineMsiRemoteCustomAction *iface, LPCGUID custom_action_guid, INT *type, MSIHANDLE *handle, BSTR *dll, BSTR *func, IWineMsiRemotePackage **remote_package)
Definition: custom.c:1434
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define LIST_ENTRY(type)
Definition: queue.h:175
static void release_custom_action_data(msi_custom_action_info *info)
Definition: custom.c:390
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
#define SEQUENCE_UI
Definition: msipriv.h:695
#define GetEnvironmentVariableW(x, y, z)
Definition: compat.h:420
const GUID IID_IClassFactory
BOOL WINAPI ReadFile(IN HANDLE hFile, IN LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:123
#define memset(x, y, z)
Definition: compat.h:39
#define IsEqualCLSID(rclsid1, rclsid2)
Definition: guiddef.h:96
static msi_custom_remote_impl * impl_from_IWineMsiRemoteCustomAction(IWineMsiRemoteCustomAction *iface)
Definition: custom.c:1397
static WCHAR * strdupAtoW(const char *str)
Definition: main.c:65
BOOL WINAPI DuplicateHandle(IN HANDLE hSourceProcessHandle, IN HANDLE hSourceHandle, IN HANDLE hTargetProcessHandle, OUT LPHANDLE lpTargetHandle, IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwOptions)
Definition: handle.c:149
static DWORD ACTION_CallScript(const GUID *guid)
Definition: custom.c:923
#define __EXCEPT_PAGE_FAULT
Definition: compat.h:71
static msi_custom_action_info * do_msidbCustomActionTypeScript(MSIPACKAGE *package, INT type, LPCWSTR script, LPCWSTR function, LPCWSTR action)
Definition: custom.c:967
_CRTIMP int __cdecl read(_In_ int _FileHandle, _Out_writes_bytes_(_MaxCharCount) void *_DstBuf, _In_ unsigned int _MaxCharCount)
static const WCHAR szCustomActionData[]
Definition: msipriv.h:1139
DWORD WINAPI GetCurrentProcessId(VOID)
Definition: proc.c:1158
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
void msi_dialog_check_messages(HANDLE handle)
Definition: dialog.c:3979
UINT msi_schedule_action(MSIPACKAGE *package, UINT script, const WCHAR *action)
Definition: custom.c:71
struct png_info_def *typedef unsigned char **typedef struct png_info_def *typedef struct png_info_def *typedef struct png_info_def *typedef unsigned char ** row
Definition: typeof.h:78
HMODULE hModule
Definition: animate.c:44
static CRITICAL_SECTION_DEBUG msi_custom_action_cs_debug
Definition: custom.c:60
UINT msi_register_unique_action(MSIPACKAGE *package, const WCHAR *action)
Definition: custom.c:94
Definition: fci.c:126
LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop) DECLSPEC_HIDDEN
Definition: package.c:2370