ReactOS  0.4.15-dev-1177-g6cb3b62
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 #include "wine/asm.h"
24 
25 #define COBJMACROS
26 
27 #include <stdarg.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winerror.h"
31 #include "msidefs.h"
32 #include "winuser.h"
33 #include "objbase.h"
34 #include "oleauto.h"
35 
36 #include "msipriv.h"
37 #include "msiserver.h"
38 #include "wine/debug.h"
39 #include "wine/unicode.h"
40 #include "wine/exception.h"
41 
42 #ifdef _MSC_VER
43 #include "msvchelper.h"
44 #endif
45 
47 
48 #define CUSTOM_ACTION_TYPE_MASK 0x3F
49 
50 typedef struct tagMSIRUNNINGACTION
51 {
52  struct list entry;
57 
59 
62 {
63  0, 0, &msi_custom_action_cs,
66  0, 0, { (DWORD_PTR)(__FILE__ ": msi_custom_action_cs") }
67 };
69 
71 
73 {
74  UINT count;
75  WCHAR **newbuf = NULL;
76 
77  if (script >= SCRIPT_MAX)
78  {
79  FIXME("Unknown script requested %u\n", script);
80  return ERROR_FUNCTION_FAILED;
81  }
82  TRACE("Scheduling action %s in script %u\n", debugstr_w(action), script);
83 
84  count = package->script_actions_count[script];
85  package->script_actions_count[script]++;
86  if (count != 0) newbuf = msi_realloc( package->script_actions[script],
87  package->script_actions_count[script] * sizeof(WCHAR *) );
88  else newbuf = msi_alloc( sizeof(WCHAR *) );
89 
90  newbuf[count] = strdupW( action );
91  package->script_actions[script] = newbuf;
92  return ERROR_SUCCESS;
93 }
94 
96 {
97  UINT count;
98  WCHAR **newbuf = NULL;
99 
100  TRACE("Registering %s as unique action\n", debugstr_w(action));
101 
102  count = package->unique_actions_count;
103  package->unique_actions_count++;
104  if (count != 0) newbuf = msi_realloc( package->unique_actions,
105  package->unique_actions_count * sizeof(WCHAR *) );
106  else newbuf = msi_alloc( sizeof(WCHAR *) );
107 
108  newbuf[count] = strdupW( action );
109  package->unique_actions = newbuf;
110  return ERROR_SUCCESS;
111 }
112 
114 {
115  UINT i;
116 
117  for (i = 0; i < package->unique_actions_count; i++)
118  {
119  if (!strcmpW( package->unique_actions[i], action )) return TRUE;
120  }
121  return FALSE;
122 }
123 
125 {
128  {
129  if (!(package->InWhatSequence & SEQUENCE_UI &&
130  package->InWhatSequence & SEQUENCE_EXEC))
131  {
132  TRACE("Skipping action due to dbCustomActionTypeClientRepeat option.\n");
133  return FALSE;
134  }
135  }
137  {
138  if (package->InWhatSequence & SEQUENCE_UI &&
139  package->InWhatSequence & SEQUENCE_EXEC )
140  {
141  TRACE("Skipping action due to msidbCustomActionTypeFirstSequence option.\n");
142  return FALSE;
143  }
144  }
146  {
147  if (msi_action_is_unique(package, action))
148  {
149  TRACE("Skipping action due to msidbCustomActionTypeOncePerProcess option.\n");
150  return FALSE;
151  }
152  else
154  }
155 
156  return TRUE;
157 }
158 
159 /* stores the following properties before the action:
160  *
161  * [CustomActionData<=>UserSID<=>ProductCode]Action
162  */
164  LPCWSTR usersid, LPCWSTR prodcode)
165 {
166  LPWSTR deferred;
167  DWORD len;
168 
169  static const WCHAR format[] = {
170  '[','%','s','<','=','>','%','s','<','=','>','%','s',']','%','s',0
171  };
172 
173  if (!actiondata)
174  return strdupW(action);
175 
176  len = lstrlenW(action) + lstrlenW(actiondata) +
177  lstrlenW(usersid) + lstrlenW(prodcode) +
178  lstrlenW(format) - 7;
179  deferred = msi_alloc(len * sizeof(WCHAR));
180 
181  sprintfW(deferred, format, actiondata, usersid, prodcode, action);
182  return deferred;
183 }
184 
185 static void set_deferred_action_props( MSIPACKAGE *package, const WCHAR *deferred_data )
186 {
187  static const WCHAR sep[] = {'<','=','>',0};
188  const WCHAR *end, *beg = deferred_data + 1;
189 
190  end = strstrW(beg, sep);
191  msi_set_property( package->db, szCustomActionData, beg, end - beg );
192  beg = end + 3;
193 
194  end = strstrW(beg, sep);
195  msi_set_property( package->db, szUserSID, beg, end - beg );
196  beg = end + 3;
197 
198  end = strchrW(beg, ']');
199  msi_set_property( package->db, szProductCode, beg, end - beg );
200 }
201 
203 {
204  WCHAR *ret;
205 
206  if (!db->tempfolder)
207  {
208  WCHAR tmp[MAX_PATH];
209  UINT len = sizeof(tmp)/sizeof(tmp[0]);
210 
211  if (msi_get_property( db, szTempFolder, tmp, &len ) ||
213  {
214  GetTempPathW( MAX_PATH, tmp );
215  }
216  if (!(db->tempfolder = strdupW( tmp ))) return NULL;
217  }
218 
219  if ((ret = msi_alloc( (strlenW( db->tempfolder ) + 20) * sizeof(WCHAR) )))
220  {
221  if (!GetTempFileNameW( db->tempfolder, szMsi, 0, ret ))
222  {
223  msi_free( ret );
224  return NULL;
225  }
226  }
227 
228  return ret;
229 }
230 
232 {
233  static const WCHAR query[] = {
234  'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
235  '`','B','i' ,'n','a','r','y','`',' ','W','H','E','R','E',' ',
236  '`','N','a','m','e','`',' ','=',' ','\'','%','s','\'',0};
237  MSIRECORD *row;
238  MSIBINARY *binary = NULL;
239  HANDLE file;
240  CHAR buffer[1024];
241  WCHAR *tmpfile;
242  DWORD sz, write;
243  UINT r;
244 
245  if (!(tmpfile = msi_create_temp_file( package->db ))) return NULL;
246 
247  if (!(row = MSI_QueryGetRecord( package->db, query, source ))) goto error;
248  if (!(binary = msi_alloc_zero( sizeof(MSIBINARY) ))) goto error;
249 
251  if (file == INVALID_HANDLE_VALUE) goto error;
252 
253  do
254  {
255  sz = sizeof(buffer);
256  r = MSI_RecordReadStream( row, 2, buffer, &sz );
257  if (r != ERROR_SUCCESS)
258  {
259  ERR("Failed to get stream\n");
260  break;
261  }
262  WriteFile( file, buffer, sz, &write, NULL );
263  } while (sz == sizeof buffer);
264 
265  CloseHandle( file );
266  if (r != ERROR_SUCCESS) goto error;
267 
268  /* keep a reference to prevent the dll from being unloaded */
269  if (dll && !(binary->module = LoadLibraryW( tmpfile )))
270  {
271  ERR( "failed to load dll %s (%u)\n", debugstr_w( tmpfile ), GetLastError() );
272  }
273  binary->source = strdupW( source );
274  binary->tmpfile = tmpfile;
275  list_add_tail( &package->binaries, &binary->entry );
276 
277  msiobj_release( &row->hdr );
278  return binary;
279 
280 error:
281  if (row) msiobj_release( &row->hdr );
282  DeleteFileW( tmpfile );
283  msi_free( tmpfile );
284  msi_free( binary );
285  return NULL;
286 }
287 
289 {
290  MSIBINARY *binary;
291 
293  {
294  if (!strcmpW( binary->source, source ))
295  return binary;
296  }
297 
298  return create_temp_binary( package, source, dll );
299 }
300 
303 {
305 
306  action = msi_alloc( sizeof(MSIRUNNINGACTION) );
307 
308  action->handle = Handle;
309  action->process = process;
310  action->name = strdupW(name);
311 
312  list_add_tail( &package->RunningActions, &action->entry );
313 }
314 
316 {
317  DWORD rc = 0;
318 
319  GetExitCodeProcess( process, &rc );
320  TRACE("exit code is %u\n", rc);
321  if (rc != 0)
322  return ERROR_FUNCTION_FAILED;
323  return ERROR_SUCCESS;
324 }
325 
327 {
328  DWORD rc = 0;
329 
330  GetExitCodeThread( thread, &rc );
331 
332  switch (rc)
333  {
335  case ERROR_SUCCESS:
338  return rc;
339  case ERROR_NO_MORE_ITEMS:
340  return ERROR_SUCCESS;
342  ACTION_ForceReboot( package );
343  return ERROR_SUCCESS;
344  default:
345  ERR("Invalid Return Code %d\n",rc);
346  return ERROR_INSTALL_FAILURE;
347  }
348 }
349 
352 {
353  UINT rc = ERROR_SUCCESS;
354 
356  {
357  TRACE("waiting for %s\n", debugstr_w(name));
358 
360 
363 
365  }
366  else
367  {
368  TRACE("%s running in background\n", debugstr_w(name));
369 
372  else
374  }
375 
376  return rc;
377 }
378 
379 typedef struct _msi_custom_action_info {
380  struct list entry;
390 
392 {
394 
395  if (!--info->refs)
396  {
397  list_remove( &info->entry );
398  if (info->handle)
399  CloseHandle( info->handle );
400  msi_free( info->action );
401  msi_free( info->source );
402  msi_free( info->target );
403  msiobj_release( &info->package->hdr );
404  msi_free( info );
405  }
406 
408 }
409 
410 /* must be called inside msi_custom_action_cs if info is in the pending custom actions list */
412 {
413  info->refs++;
414  }
415 
417 {
418  UINT rc = ERROR_SUCCESS;
419 
420  if (!(info->type & msidbCustomActionTypeAsync))
421  {
422  TRACE("waiting for %s\n", debugstr_w( info->action ));
423 
424  msi_dialog_check_messages( info->handle );
425 
426  if (!(info->type & msidbCustomActionTypeContinue))
427  rc = custom_get_thread_return( info->package, info->handle );
428 
430  }
431  else
432  {
433  TRACE("%s running in background\n", debugstr_w( info->action ));
434  }
435 
436  return rc;
437 }
438 
440 {
442  BOOL found = FALSE;
443 
445 
447  {
448  if (IsEqualGUID( &info->guid, guid ))
449  {
451  found = TRUE;
452  break;
453  }
454  }
455 
457 
458  if (!found)
459  return NULL;
460 
461  return info;
462 }
463 
465 {
466  LPWSTR msg;
467  WCHAR val[MAX_PATH];
468 
469  static const WCHAR MsiBreak[] = { 'M','s','i','B','r','e','a','k',0 };
470  static const WCHAR WindowsInstaller[] = {
471  'W','i','n','d','o','w','s',' ','I','n','s','t','a','l','l','e','r',0
472  };
473 
474  static const WCHAR format[] = {
475  'T','o',' ','d','e','b','u','g',' ','y','o','u','r',' ',
476  'c','u','s','t','o','m',' ','a','c','t','i','o','n',',',' ',
477  'a','t','t','a','c','h',' ','y','o','u','r',' ','d','e','b','u','g','g','e','r',' ',
478  't','o',' ','p','r','o','c','e','s','s',' ','%','i',' ','(','0','x','%','X',')',' ',
479  'a','n','d',' ','p','r','e','s','s',' ','O','K',0
480  };
481 
482  if( !GetEnvironmentVariableW( MsiBreak, val, MAX_PATH ))
483  return;
484 
485  if( strcmpiW( val, target ))
486  return;
487 
488  msg = msi_alloc( (lstrlenW(format) + 10) * sizeof(WCHAR) );
489  if (!msg)
490  return;
491 
494  msi_free(msg);
495  DebugBreak();
496 }
497 
499  BSTR *dll, BSTR *funcname,
500  IWineMsiRemotePackage **package )
501 {
502  IClassFactory *cf = NULL;
504  HRESULT r;
505 
506  r = DllGetClassObject( &CLSID_WineMsiRemoteCustomAction,
507  &IID_IClassFactory, (LPVOID *)&cf );
508  if (FAILED(r))
509  {
510  ERR("failed to get IClassFactory interface\n");
511  return ERROR_FUNCTION_FAILED;
512  }
513 
514  r = IClassFactory_CreateInstance( cf, NULL, &IID_IWineMsiRemoteCustomAction, (LPVOID *)&rca );
515  if (FAILED(r))
516  {
517  ERR("failed to get IWineMsiRemoteCustomAction interface\n");
518  return ERROR_FUNCTION_FAILED;
519  }
520 
521  r = IWineMsiRemoteCustomAction_GetActionInfo( rca, guid, type, handle, dll, funcname, package );
522  IWineMsiRemoteCustomAction_Release( rca );
523  if (FAILED(r))
524  {
525  ERR("GetActionInfo failed\n");
526  return ERROR_FUNCTION_FAILED;
527  }
528 
529  return ERROR_SUCCESS;
530 }
531 
532 #ifdef __i386__
535  "pushl %ebp\n\t"
536  __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
537  __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
538  "movl %esp,%ebp\n\t"
539  __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
540  "subl $4,%esp\n\t"
541  "pushl 12(%ebp)\n\t"
542  "movl 8(%ebp),%eax\n\t"
543  "call *%eax\n\t"
544  "leave\n\t"
545  __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
546  __ASM_CFI(".cfi_same_value %ebp\n\t")
547  "ret" )
548 #else
550 {
551  return proc(handle);
552 }
553 #endif
554 
556 {
558  MSIHANDLE hPackage, handle;
559  HANDLE hModule;
560  LPSTR proc;
562  BSTR dll = NULL, function = NULL;
563  INT type;
564  IWineMsiRemotePackage *remote_package = NULL;
565 
566  TRACE("%s\n", debugstr_guid( guid ));
567 
568  r = get_action_info( guid, &type, &handle, &dll, &function, &remote_package );
569  if (r != ERROR_SUCCESS)
570  return r;
571 
572  hModule = LoadLibraryW( dll );
573  if (!hModule)
574  {
575  ERR( "failed to load dll %s (%u)\n", debugstr_w( dll ), GetLastError() );
576  return ERROR_SUCCESS;
577  }
578 
579  proc = strdupWtoA( function );
581  msi_free( proc );
582  if (fn)
583  {
584  hPackage = alloc_msi_remote_handle( (IUnknown *)remote_package );
585  if (hPackage)
586  {
587  IWineMsiRemotePackage_SetMsiHandle( remote_package, handle );
588  TRACE("calling %s\n", debugstr_w( function ) );
589  handle_msi_break( function );
590 
591  __TRY
592  {
593  r = CUSTOMPROC_wrapper( fn, hPackage );
594  }
596  {
597  ERR("Custom action (%s:%s) caused a page fault: %08x\n",
598  debugstr_w(dll), debugstr_w(function), GetExceptionCode());
599  r = ERROR_SUCCESS;
600  }
601  __ENDTRY;
602 
603  MsiCloseHandle( hPackage );
604  }
605  else
606  ERR("failed to create handle for %p\n", remote_package );
607  }
608  else
609  ERR("GetProcAddress(%s) failed\n", debugstr_w( function ) );
610 
612 
613  IWineMsiRemotePackage_Release( remote_package );
614  SysFreeString( dll );
615  SysFreeString( function );
617 
618  return r;
619 }
620 
622 {
623  LPGUID guid = arg;
624  DWORD rc = 0;
625 
626  TRACE("custom action (%x) started\n", GetCurrentThreadId() );
627 
629 
630  TRACE("custom action (%x) returned %i\n", GetCurrentThreadId(), rc );
631 
633  return rc;
634 }
635 
638 {
640 
641  info = msi_alloc( sizeof *info );
642  if (!info)
643  return NULL;
644 
645  msiobj_addref( &package->hdr );
646  info->refs = 2; /* 1 for our caller and 1 for thread we created */
647  info->package = package;
648  info->type = type;
649  info->target = strdupW( target );
650  info->source = strdupW( source );
651  info->action = strdupW( action );
652  CoCreateGuid( &info->guid );
653 
657 
658  info->handle = CreateThread( NULL, 0, DllThread, &info->guid, 0, NULL );
659  if (!info->handle)
660  {
661  /* release both references */
664  return NULL;
665  }
666 
667  return info;
668 }
669 
670 static UINT HANDLE_CustomType1( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
671  INT type, const WCHAR *action )
672 {
674  MSIBINARY *binary;
675 
676  if (!(binary = get_temp_binary( package, source, TRUE )))
677  return ERROR_FUNCTION_FAILED;
678 
679  TRACE("Calling function %s from %s\n", debugstr_w(target), debugstr_w(binary->tmpfile));
680 
681  info = do_msidbCustomActionTypeDll( package, type, binary->tmpfile, target, action );
682  return wait_thread_handle( info );
683 }
684 
685 static HANDLE execute_command( const WCHAR *app, WCHAR *arg, const WCHAR *dir )
686 {
687  static const WCHAR dotexeW[] = {'.','e','x','e',0};
688  STARTUPINFOW si;
690  WCHAR *exe = NULL, *cmd = NULL, *p;
691  BOOL ret;
692 
693  if (app)
694  {
695  int len_arg = 0;
696  DWORD len_exe;
697 
698  if (!(exe = msi_alloc( MAX_PATH * sizeof(WCHAR) ))) return INVALID_HANDLE_VALUE;
699  len_exe = SearchPathW( NULL, app, dotexeW, MAX_PATH, exe, NULL );
700  if (len_exe >= MAX_PATH)
701  {
702  msi_free( exe );
703  if (!(exe = msi_alloc( len_exe * sizeof(WCHAR) ))) return INVALID_HANDLE_VALUE;
704  len_exe = SearchPathW( NULL, app, dotexeW, len_exe, exe, NULL );
705  }
706  if (!len_exe)
707  {
708  ERR("can't find executable %u\n", GetLastError());
709  msi_free( exe );
710  return INVALID_HANDLE_VALUE;
711  }
712 
713  if (arg) len_arg = strlenW( arg );
714  if (!(cmd = msi_alloc( (len_exe + len_arg + 4) * sizeof(WCHAR) )))
715  {
716  msi_free( exe );
717  return INVALID_HANDLE_VALUE;
718  }
719  p = cmd;
720  if (strchrW( exe, ' ' ))
721  {
722  *p++ = '\"';
723  memcpy( p, exe, len_exe * sizeof(WCHAR) );
724  p += len_exe;
725  *p++ = '\"';
726  *p = 0;
727  }
728  else
729  {
730  strcpyW( p, exe );
731  p += len_exe;
732  }
733  if (arg)
734  {
735  *p++ = ' ';
736  memcpy( p, arg, len_arg * sizeof(WCHAR) );
737  p[len_arg] = 0;
738  }
739  }
740  memset( &si, 0, sizeof(STARTUPINFOW) );
741  ret = CreateProcessW( exe, exe ? cmd : arg, NULL, NULL, FALSE, 0, NULL, dir, &si, &info );
742  msi_free( cmd );
743  msi_free( exe );
744  if (!ret)
745  {
746  ERR("unable to execute command %u\n", GetLastError());
747  return INVALID_HANDLE_VALUE;
748  }
749  CloseHandle( info.hThread );
750  return info.hProcess;
751 }
752 
753 static UINT HANDLE_CustomType2( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
754  INT type, const WCHAR *action )
755 {
756  MSIBINARY *binary;
757  HANDLE handle;
758  WCHAR *arg;
759 
760  if (!(binary = get_temp_binary( package, source, FALSE ))) return ERROR_FUNCTION_FAILED;
761 
762  deformat_string( package, target, &arg );
763  TRACE("exe %s arg %s\n", debugstr_w(binary->tmpfile), debugstr_w(arg));
764 
765  handle = execute_command( binary->tmpfile, arg, szCRoot );
766  msi_free( arg );
768  return wait_process_handle( package, type, handle, action );
769 }
770 
771 static UINT HANDLE_CustomType17( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
772  INT type, const WCHAR *action )
773 {
775  MSIFILE *file;
776 
777  TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
778 
779  file = msi_get_loaded_file( package, source );
780  if (!file)
781  {
782  ERR("invalid file key %s\n", debugstr_w( source ));
783  return ERROR_FUNCTION_FAILED;
784  }
785 
786  info = do_msidbCustomActionTypeDll( package, type, file->TargetPath, target, action );
787  return wait_thread_handle( info );
788 }
789 
790 static UINT HANDLE_CustomType18( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
791  INT type, const WCHAR *action )
792 {
793  MSIFILE *file;
794  HANDLE handle;
795  WCHAR *arg;
796 
797  if (!(file = msi_get_loaded_file( package, source ))) return ERROR_FUNCTION_FAILED;
798 
799  deformat_string( package, target, &arg );
800  TRACE("exe %s arg %s\n", debugstr_w(file->TargetPath), debugstr_w(arg));
801 
802  handle = execute_command( file->TargetPath, arg, szCRoot );
803  msi_free( arg );
805  return wait_process_handle( package, type, handle, action );
806 }
807 
808 static UINT HANDLE_CustomType19( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
809  INT type, const WCHAR *action )
810 {
811  static const WCHAR query[] = {
812  'S','E','L','E','C','T',' ','`','M','e','s','s','a','g','e','`',' ',
813  'F','R','O','M',' ','`','E','r','r','o','r','`',' ',
814  'W','H','E','R','E',' ','`','E','r','r','o','r','`',' ','=',' ',
815  '%','s',0
816  };
817  MSIRECORD *row = 0;
818  LPWSTR deformated = NULL;
819 
820  deformat_string( package, target, &deformated );
821 
822  /* first try treat the error as a number */
823  row = MSI_QueryGetRecord( package->db, query, deformated );
824  if( row )
825  {
829  msiobj_release( &row->hdr );
830  }
831  else if ((package->ui_level & INSTALLUILEVEL_MASK) != INSTALLUILEVEL_NONE)
832  MessageBoxW( NULL, deformated, NULL, MB_OK );
833 
834  msi_free( deformated );
835 
836  return ERROR_INSTALL_FAILURE;
837 }
838 
839 static UINT HANDLE_CustomType23( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
840  INT type, const WCHAR *action )
841 {
842  static const WCHAR msiexecW[] = {'m','s','i','e','x','e','c',0};
843  static const WCHAR paramsW[] = {'/','q','b',' ','/','i',' '};
844  WCHAR *dir, *arg, *p;
845  UINT len_src, len_dir, len_tgt, len = sizeof(paramsW)/sizeof(paramsW[0]);
846  HANDLE handle;
847 
848  if (!(dir = msi_dup_property( package->db, szOriginalDatabase ))) return ERROR_OUTOFMEMORY;
849  if (!(p = strrchrW( dir, '\\' )) && !(p = strrchrW( dir, '/' )))
850  {
851  msi_free( dir );
852  return ERROR_FUNCTION_FAILED;
853  }
854  *p = 0;
855  len_dir = p - dir;
856  len_src = strlenW( source );
857  len_tgt = strlenW( target );
858  if (!(arg = msi_alloc( (len + len_dir + len_src + len_tgt + 5) * sizeof(WCHAR) )))
859  {
860  msi_free( dir );
861  return ERROR_OUTOFMEMORY;
862  }
863  memcpy( arg, paramsW, sizeof(paramsW) );
864  arg[len++] = '"';
865  memcpy( arg + len, dir, len_dir * sizeof(WCHAR) );
866  len += len_dir;
867  arg[len++] = '\\';
868  memcpy( arg + len, source, len_src * sizeof(WCHAR) );
869  len += len_src;
870  arg[len++] = '"';
871  arg[len++] = ' ';
872  strcpyW( arg + len, target );
873 
874  TRACE("installing %s concurrently\n", debugstr_w(source));
875 
876  handle = execute_command( msiexecW, arg, dir );
877  msi_free( dir );
878  msi_free( arg );
880  return wait_process_handle( package, type, handle, action );
881 }
882 
883 static UINT HANDLE_CustomType50( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
884  INT type, const WCHAR *action )
885 {
886  WCHAR *exe, *arg;
887  HANDLE handle;
888 
889  if (!(exe = msi_dup_property( package->db, source ))) return ERROR_SUCCESS;
890 
891  deformat_string( package, target, &arg );
892  TRACE("exe %s arg %s\n", debugstr_w(exe), debugstr_w(arg));
893 
894  handle = execute_command( exe, arg, szCRoot );
895  msi_free( exe );
896  msi_free( arg );
898  return wait_process_handle( package, type, handle, action );
899 }
900 
901 static UINT HANDLE_CustomType34( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
902  INT type, const WCHAR *action )
903 {
904  const WCHAR *workingdir = NULL;
905  HANDLE handle;
906  WCHAR *cmd;
907 
908  if (source)
909  {
910  workingdir = msi_get_target_folder( package, source );
911  if (!workingdir) return ERROR_FUNCTION_FAILED;
912  }
913  deformat_string( package, target, &cmd );
914  if (!cmd) return ERROR_FUNCTION_FAILED;
915 
916  TRACE("cmd %s dir %s\n", debugstr_w(cmd), debugstr_w(workingdir));
917 
918  handle = execute_command( NULL, cmd, workingdir );
919  msi_free( cmd );
921  return wait_process_handle( package, type, handle, action );
922 }
923 
925 {
927  MSIHANDLE hPackage;
929 
931  if (!info)
932  {
933  ERR("failed to find action %s\n", debugstr_guid( guid) );
934  return ERROR_FUNCTION_FAILED;
935  }
936 
937  TRACE("function %s, script %s\n", debugstr_w( info->target ), debugstr_w( info->source ) );
938 
939  hPackage = alloc_msihandle( &info->package->hdr );
940  if (hPackage)
941  {
942  r = call_script( hPackage, info->type, info->source, info->target, info->action );
943  TRACE("script returned %u\n", r);
944  MsiCloseHandle( hPackage );
945  }
946  else
947  ERR("failed to create handle for %p\n", info->package );
948 
950  return r;
951 }
952 
954 {
955  LPGUID guid = arg;
956  DWORD rc;
957 
958  TRACE("custom action (%x) started\n", GetCurrentThreadId() );
959 
960  rc = ACTION_CallScript( guid );
961 
962  TRACE("custom action (%x) returned %i\n", GetCurrentThreadId(), rc );
963 
965  return rc;
966 }
967 
969  MSIPACKAGE *package, INT type, LPCWSTR script, LPCWSTR function, LPCWSTR action )
970 {
972 
973  info = msi_alloc( sizeof *info );
974  if (!info)
975  return NULL;
976 
977  msiobj_addref( &package->hdr );
978  info->refs = 2; /* 1 for our caller and 1 for thread we created */
979  info->package = package;
980  info->type = type;
981  info->target = strdupW( function );
982  info->source = strdupW( script );
983  info->action = strdupW( action );
984  CoCreateGuid( &info->guid );
985 
989 
990  info->handle = CreateThread( NULL, 0, ScriptThread, &info->guid, 0, NULL );
991  if (!info->handle)
992  {
993  /* release both references */
996  return NULL;
997  }
998 
999  return info;
1000 }
1001 
1002 static UINT HANDLE_CustomType37_38( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
1003  INT type, const WCHAR *action )
1004 {
1006 
1007  TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
1008 
1010  return wait_thread_handle( info );
1011 }
1012 
1013 static UINT HANDLE_CustomType5_6( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
1014  INT type, const WCHAR *action )
1015 {
1016  static const WCHAR query[] = {
1017  'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
1018  '`','B','i' ,'n','a','r','y','`',' ','W','H','E','R','E',' ',
1019  '`','N','a','m','e','`',' ','=',' ','\'','%','s','\'',0};
1020  MSIRECORD *row = NULL;
1022  CHAR *buffer = NULL;
1023  WCHAR *bufferw = NULL;
1024  DWORD sz = 0;
1025  UINT r;
1026 
1027  TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
1028 
1029  row = MSI_QueryGetRecord(package->db, query, source);
1030  if (!row)
1031  return ERROR_FUNCTION_FAILED;
1032 
1033  r = MSI_RecordReadStream(row, 2, NULL, &sz);
1034  if (r != ERROR_SUCCESS) goto done;
1035 
1036  buffer = msi_alloc( sz + 1 );
1037  if (!buffer)
1038  {
1040  goto done;
1041  }
1042 
1043  r = MSI_RecordReadStream(row, 2, buffer, &sz);
1044  if (r != ERROR_SUCCESS)
1045  goto done;
1046 
1047  buffer[sz] = 0;
1048  bufferw = strdupAtoW(buffer);
1049  if (!bufferw)
1050  {
1052  goto done;
1053  }
1054 
1055  info = do_msidbCustomActionTypeScript( package, type, bufferw, target, action );
1056  r = wait_thread_handle( info );
1057 
1058 done:
1059  msi_free(bufferw);
1060  msi_free(buffer);
1061  msiobj_release(&row->hdr);
1062  return r;
1063 }
1064 
1065 static UINT HANDLE_CustomType21_22( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
1066  INT type, const WCHAR *action )
1067 {
1069  MSIFILE *file;
1070  HANDLE hFile;
1071  DWORD sz, szHighWord = 0, read;
1072  CHAR *buffer=NULL;
1073  WCHAR *bufferw=NULL;
1074  BOOL bRet;
1075  UINT r;
1076 
1077  TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
1078 
1079  file = msi_get_loaded_file(package, source);
1080  if (!file)
1081  {
1082  ERR("invalid file key %s\n", debugstr_w(source));
1083  return ERROR_FUNCTION_FAILED;
1084  }
1085 
1088 
1089  sz = GetFileSize(hFile, &szHighWord);
1090  if (sz == INVALID_FILE_SIZE || szHighWord != 0)
1091  {
1092  CloseHandle(hFile);
1093  return ERROR_FUNCTION_FAILED;
1094  }
1095  buffer = msi_alloc( sz + 1 );
1096  if (!buffer)
1097  {
1098  CloseHandle(hFile);
1099  return ERROR_FUNCTION_FAILED;
1100  }
1101  bRet = ReadFile(hFile, buffer, sz, &read, NULL);
1102  CloseHandle(hFile);
1103  if (!bRet)
1104  {
1106  goto done;
1107  }
1108  buffer[read] = 0;
1109  bufferw = strdupAtoW(buffer);
1110  if (!bufferw)
1111  {
1113  goto done;
1114  }
1115  info = do_msidbCustomActionTypeScript( package, type, bufferw, target, action );
1116  r = wait_thread_handle( info );
1117 
1118 done:
1119  msi_free(bufferw);
1120  msi_free(buffer);
1121  return r;
1122 }
1123 
1124 static UINT HANDLE_CustomType53_54( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
1125  INT type, const WCHAR *action )
1126 {
1128  WCHAR *prop;
1129 
1130  TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
1131 
1132  prop = msi_dup_property( package->db, source );
1133  if (!prop) return ERROR_SUCCESS;
1134 
1135  info = do_msidbCustomActionTypeScript( package, type, prop, NULL, action );
1136  msi_free(prop);
1137  return wait_thread_handle( info );
1138 }
1139 
1141 {
1142  switch (script)
1143  {
1144  case SCRIPT_NONE:
1145  case SCRIPT_INSTALL:
1147  case SCRIPT_COMMIT:
1148  return (type & msidbCustomActionTypeCommit);
1149  case SCRIPT_ROLLBACK:
1151  default:
1152  ERR("unhandled script %u\n", script);
1153  }
1154  return FALSE;
1155 }
1156 
1158 {
1159  WCHAR *actiondata = msi_dup_property( package->db, action );
1160  WCHAR *usersid = msi_dup_property( package->db, szUserSID );
1161  WCHAR *prodcode = msi_dup_property( package->db, szProductCode );
1162  WCHAR *deferred = msi_get_deferred_action( action, actiondata, usersid, prodcode );
1163 
1164  if (!deferred)
1165  {
1166  msi_free( actiondata );
1167  msi_free( usersid );
1168  msi_free( prodcode );
1169  return ERROR_OUTOFMEMORY;
1170  }
1172  {
1173  TRACE("deferring commit action\n");
1174  msi_schedule_action( package, SCRIPT_COMMIT, deferred );
1175  }
1177  {
1178  TRACE("deferring rollback action\n");
1179  msi_schedule_action( package, SCRIPT_ROLLBACK, deferred );
1180  }
1181  else
1182  {
1183  TRACE("deferring install action\n");
1184  msi_schedule_action( package, SCRIPT_INSTALL, deferred );
1185  }
1186 
1187  msi_free( actiondata );
1188  msi_free( usersid );
1189  msi_free( prodcode );
1190  msi_free( deferred );
1191  return ERROR_SUCCESS;
1192 }
1193 
1195 {
1196  static const WCHAR query[] = {
1197  'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
1198  '`','C','u','s','t','o','m','A','c','t','i','o','n','`',' ','W','H','E','R','E',' ',
1199  '`','A','c','t','i' ,'o','n','`',' ','=',' ','\'','%','s','\'',0};
1200  UINT rc = ERROR_SUCCESS;
1201  MSIRECORD *row;
1202  UINT type;
1203  const WCHAR *source, *target, *ptr, *deferred_data = NULL;
1204  WCHAR *deformated = NULL;
1205  int len;
1206 
1207  /* deferred action: [properties]Action */
1208  if ((ptr = strrchrW(action, ']')))
1209  {
1210  deferred_data = action;
1211  action = ptr + 1;
1212  }
1213 
1214  row = MSI_QueryGetRecord( package->db, query, action );
1215  if (!row)
1217 
1221 
1222  TRACE("Handling custom action %s (%x %s %s)\n",debugstr_w(action),type,
1224 
1225  /* handle some of the deferred actions */
1227  FIXME("msidbCustomActionTypeTSAware not handled\n");
1228 
1230  {
1232  WARN("msidbCustomActionTypeNoImpersonate not handled\n");
1233 
1235  {
1236  rc = defer_custom_action( package, action, type );
1237  goto end;
1238  }
1239  else
1240  {
1241  LPWSTR actiondata = msi_dup_property( package->db, action );
1242 
1244  package->scheduled_action_running = TRUE;
1245 
1247  package->commit_action_running = TRUE;
1248 
1250  package->rollback_action_running = TRUE;
1251 
1252  if (deferred_data)
1253  set_deferred_action_props(package, deferred_data);
1254  else if (actiondata)
1255  msi_set_property( package->db, szCustomActionData, actiondata, -1 );
1256  else
1257  msi_set_property( package->db, szCustomActionData, szEmpty, -1 );
1258 
1259  msi_free(actiondata);
1260  }
1261  }
1262  else if (!check_execution_scheduling_options(package,action,type))
1263  {
1264  rc = ERROR_SUCCESS;
1265  goto end;
1266  }
1267 
1268  switch (type & CUSTOM_ACTION_TYPE_MASK)
1269  {
1270  case 1: /* DLL file stored in a Binary table stream */
1271  rc = HANDLE_CustomType1(package,source,target,type,action);
1272  break;
1273  case 2: /* EXE file stored in a Binary table stream */
1274  rc = HANDLE_CustomType2(package,source,target,type,action);
1275  break;
1276  case 18: /*EXE file installed with package */
1278  break;
1279  case 19: /* Error that halts install */
1281  break;
1282  case 17:
1284  break;
1285  case 23: /* installs another package in the source tree */
1286  deformat_string(package,target,&deformated);
1287  rc = HANDLE_CustomType23(package,source,deformated,type,action);
1288  msi_free(deformated);
1289  break;
1290  case 50: /*EXE file specified by a property value */
1292  break;
1293  case 34: /*EXE to be run in specified directory */
1295  break;
1296  case 35: /* Directory set with formatted text. */
1297  deformat_string(package,target,&deformated);
1298  MSI_SetTargetPathW(package, source, deformated);
1299  msi_free(deformated);
1300  break;
1301  case 51: /* Property set with formatted text. */
1302  if (!source)
1303  break;
1304 
1305  len = deformat_string( package, target, &deformated );
1306  rc = msi_set_property( package->db, source, deformated, len );
1307  if (rc == ERROR_SUCCESS && !strcmpW( source, szSourceDir ))
1308  msi_reset_folders( package, TRUE );
1309  msi_free(deformated);
1310  break;
1311  case 37: /* JScript/VBScript text stored in target column. */
1312  case 38:
1314  break;
1315  case 5:
1316  case 6: /* JScript/VBScript file stored in a Binary table stream. */
1318  break;
1319  case 21: /* JScript/VBScript file installed with the product. */
1320  case 22:
1322  break;
1323  case 53: /* JScript/VBScript text specified by a property value. */
1324  case 54:
1326  break;
1327  default:
1328  FIXME("unhandled action type %u (%s %s)\n", type & CUSTOM_ACTION_TYPE_MASK,
1330  }
1331 
1332 end:
1333  package->scheduled_action_running = FALSE;
1334  package->commit_action_running = FALSE;
1335  package->rollback_action_running = FALSE;
1336  msiobj_release(&row->hdr);
1337  return rc;
1338 }
1339 
1341 {
1342  struct list *item;
1343  HANDLE *wait_handles;
1344  unsigned int handle_count, i;
1346 
1347  while ((item = list_head( &package->RunningActions )))
1348  {
1350 
1351  list_remove( &action->entry );
1352 
1353  TRACE("waiting for %s\n", debugstr_w( action->name ) );
1354  msi_dialog_check_messages( action->handle );
1355 
1356  CloseHandle( action->handle );
1357  msi_free( action->name );
1358  msi_free( action );
1359  }
1360 
1362 
1363  handle_count = list_count( &msi_pending_custom_actions );
1364  wait_handles = msi_alloc( handle_count * sizeof(HANDLE) );
1365 
1366  handle_count = 0;
1368  {
1369  if (info->package == package )
1370  {
1371  if (DuplicateHandle(GetCurrentProcess(), info->handle, GetCurrentProcess(), &wait_handles[handle_count], SYNCHRONIZE, FALSE, 0))
1372  handle_count++;
1373  }
1374  }
1375 
1377 
1378  for (i = 0; i < handle_count; i++)
1379  {
1380  msi_dialog_check_messages( wait_handles[i] );
1381  CloseHandle( wait_handles[i] );
1382  }
1383  msi_free( wait_handles );
1384 
1387  {
1388  if (info->package == package) release_custom_action_data( info );
1389  }
1391 }
1392 
1393 typedef struct _msi_custom_remote_impl {
1397 
1399 {
1400  return CONTAINING_RECORD(iface, msi_custom_remote_impl, IWineMsiRemoteCustomAction_iface);
1401 }
1402 
1404  REFIID riid,LPVOID *ppobj)
1405 {
1406  if( IsEqualCLSID( riid, &IID_IUnknown ) ||
1407  IsEqualCLSID( riid, &IID_IWineMsiRemoteCustomAction ) )
1408  {
1409  IWineMsiRemoteCustomAction_AddRef( iface );
1410  *ppobj = iface;
1411  return S_OK;
1412  }
1413 
1414  return E_NOINTERFACE;
1415 }
1416 
1418 {
1420 
1421  return InterlockedIncrement( &This->refs );
1422 }
1423 
1425 {
1427  ULONG r;
1428 
1429  r = InterlockedDecrement( &This->refs );
1430  if (r == 0)
1431  msi_free( This );
1432  return r;
1433 }
1434 
1436  INT *type, MSIHANDLE *handle, BSTR *dll, BSTR *func, IWineMsiRemotePackage **remote_package )
1437 {
1439 
1440  info = find_action_by_guid( custom_action_guid );
1441  if (!info)
1442  return E_FAIL;
1443 
1444  *type = info->type;
1445  *handle = alloc_msihandle( &info->package->hdr );
1446  *dll = SysAllocString( info->source );
1447  *func = SysAllocString( info->target );
1448 
1450  return create_msi_remote_package( NULL, (LPVOID *)remote_package );
1451 }
1452 
1453 static const IWineMsiRemoteCustomActionVtbl msi_custom_remote_vtbl =
1454 {
1456  mcr_AddRef,
1457  mcr_Release,
1459 };
1460 
1462 {
1464 
1465  This = msi_alloc( sizeof *This );
1466  if (!This)
1467  return E_OUTOFMEMORY;
1468 
1469  This->IWineMsiRemoteCustomAction_iface.lpVtbl = &msi_custom_remote_vtbl;
1470  This->refs = 1;
1471 
1472  *ppObj = &This->IWineMsiRemoteCustomAction_iface;
1473 
1474  return S_OK;
1475 }
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:771
GLenum func
Definition: glext.h:6028
static BOOL check_execution_scheduling_options(MSIPACKAGE *package, LPCWSTR action, UINT options)
Definition: custom.c:124
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:1340
static UINT CUSTOMPROC_wrapper(MsiCustomActionEntryPoint proc, MSIHANDLE handle)
Definition: custom.c:549
static UINT HANDLE_CustomType18(MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, INT type, const WCHAR *action)
Definition: custom.c:790
#define CUSTOM_ACTION_TYPE_MASK
Definition: custom.c:48
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define REFIID
Definition: guiddef.h:118
UINT WINAPI MsiCloseAllHandles(void)
Definition: handle.c:326
static UINT custom_get_process_return(HANDLE process)
Definition: custom.c:315
#define CloseHandle
Definition: compat.h:487
#define E_NOINTERFACE
Definition: winerror.h:2364
static void handle_msi_break(LPCWSTR target)
Definition: custom.c:464
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:105
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:1124
static DWORD WINAPI DllThread(LPVOID arg)
Definition: custom.c:621
Definition: ftp_var.h:139
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
MSIOBJECTHDR hdr
Definition: msipriv.h:385
#define TRUE
Definition: types.h:120
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:112
BOOL msi_action_is_unique(const MSIPACKAGE *package, const WCHAR *action)
Definition: custom.c:113
static LPSTR strdupWtoA(LPCWSTR str)
Definition: hhctrl.h:296
static ULONG WINAPI mcr_AddRef(IWineMsiRemoteCustomAction *iface)
Definition: custom.c:1417
static HANDLE process
Definition: process.c:76
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define INVALID_HANDLE_VALUE
Definition: compat.h:479
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1044
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:2041
static UINT HANDLE_CustomType1(MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, INT type, const WCHAR *action)
Definition: custom.c:670
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
char * LPSTR
Definition: xmlstorage.h:182
#define lstrlenW
Definition: compat.h:498
#define E_FAIL
Definition: ddrawi.h:102
int32_t INT
Definition: typedefs.h:58
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:808
#define FILE_SHARE_READ
Definition: compat.h:136
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:58
__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:52
static MSIBINARY * get_temp_binary(MSIPACKAGE *package, LPCWSTR source, BOOL dll)
Definition: custom.c:288
#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:555
#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:901
#define FALSE
Definition: types.h:117
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:652
#define GENERIC_WRITE
Definition: nt_native.h:90
#define debugstr_w
Definition: kernel32.h:32
#define FIXME(fmt,...)
Definition: debug.h:111
static UINT wait_process_handle(MSIPACKAGE *package, UINT type, HANDLE ProcessHandle, LPCWSTR name)
Definition: custom.c:350
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:495
smooth NULL
Definition: ftsmooth.c:416
static HRESULT WINAPI mcr_QueryInterface(IWineMsiRemoteCustomAction *iface, REFIID riid, LPVOID *ppobj)
Definition: custom.c:1403
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:636
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:238
static void addref_custom_action_data(msi_custom_action_info *info)
Definition: custom.c:411
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:80
static void set_deferred_action_props(MSIPACKAGE *package, const WCHAR *deferred_data)
Definition: custom.c:185
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:883
#define debugstr_guid
Definition: kernel32.h:35
#define SEQUENCE_EXEC
Definition: msipriv.h:696
#define OPEN_EXISTING
Definition: compat.h:523
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:4595
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:1461
#define GetExceptionCode()
Definition: exception.h:69
__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:496
static void file_running_action(MSIPACKAGE *package, HANDLE Handle, BOOL process, LPCWSTR name)
Definition: custom.c:301
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:79
INSTALLUILEVEL ui_level
Definition: msipriv.h:430
const GUID IID_IUnknown
#define funcname
Definition: shellext.h:96
#define ERROR_INSTALL_FAILURE
Definition: winerror.h:961
#define MAX_PATH
Definition: compat.h:34
#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:60
MSIDATABASE * db
Definition: msipriv.h:386
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
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:380
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:753
static DWORD WINAPI ScriptThread(LPVOID arg)
Definition: custom.c:953
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:82
int ret
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
static const IWineMsiRemoteCustomActionVtbl msi_custom_remote_vtbl
Definition: custom.c:1453
#define InterlockedDecrement
Definition: armddk.h:52
static UINT defer_custom_action(MSIPACKAGE *package, const WCHAR *action, UINT type)
Definition: custom.c:1157
static UINT HANDLE_CustomType5_6(MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, INT type, const WCHAR *action)
Definition: custom.c:1013
#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
#define GetCurrentProcess()
Definition: compat.h:507
Definition: _list.h:228
#define GENERIC_READ
Definition: compat.h:135
static LPWSTR msi_get_deferred_action(LPCWSTR action, LPCWSTR actiondata, LPCWSTR usersid, LPCWSTR prodcode)
Definition: custom.c:163
#define SYNCHRONIZE
Definition: nt_native.h:61
LIST_ENTRY ProcessLocksList
Definition: winbase.h:861
_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:839
static UINT get_action_info(const GUID *guid, INT *type, MSIHANDLE *handle, BSTR *dll, BSTR *funcname, IWineMsiRemotePackage **package)
Definition: custom.c:498
UINT WINAPI MsiCloseHandle(MSIHANDLE handle)
Definition: handle.c:270
UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script)
Definition: custom.c:1194
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:110
static UINT custom_get_thread_return(MSIPACKAGE *package, HANDLE thread)
Definition: custom.c:326
static UINT wait_thread_handle(msi_custom_action_info *info)
Definition: custom.c:416
#define ERROR_INSTALL_SUSPEND
Definition: winerror.h:962
#define S_OK
Definition: intsafe.h:51
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:685
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:382
GLsizei GLsizei GLchar * source
Definition: glext.h:6048
#define sprintfW
Definition: unicode.h:58
static struct list msi_pending_custom_actions
Definition: custom.c:70
IWineMsiRemoteCustomAction IWineMsiRemoteCustomAction_iface
Definition: custom.c:1394
static ULONG WINAPI mcr_Release(IWineMsiRemoteCustomAction *iface)
Definition: custom.c:1424
MSIHANDLE alloc_msihandle(MSIOBJECTHDR *obj)
Definition: handle.c:109
#define ReadFile(a, b, c, d, e)
Definition: compat.h:490
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:231
#define CreateFileW
Definition: compat.h:489
static msi_custom_action_info * find_action_by_guid(const GUID *guid)
Definition: custom.c:439
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:202
static BOOL action_type_matches_script(UINT type, UINT script)
Definition: custom.c:1140
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:1065
#define GetProcAddress(x, y)
Definition: compat.h:501
static UINT HANDLE_CustomType37_38(MSIPACKAGE *package, const WCHAR *source, const WCHAR *target, INT type, const WCHAR *action)
Definition: custom.c:1002
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:1435
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:391
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
#define SEQUENCE_UI
Definition: msipriv.h:695
#define GetEnvironmentVariableW(x, y, z)
Definition: compat.h:503
const GUID IID_IClassFactory
#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:1398
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:924
#define __EXCEPT_PAGE_FAULT
Definition: compat.h:81
static msi_custom_action_info * do_msidbCustomActionTypeScript(MSIPACKAGE *package, INT type, LPCWSTR script, LPCWSTR function, LPCWSTR action)
Definition: custom.c:968
_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:72
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:61
UINT msi_register_unique_action(MSIPACKAGE *package, const WCHAR *action)
Definition: custom.c:95
Definition: fci.c:126
LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop) DECLSPEC_HIDDEN
Definition: package.c:2370