ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

queue.c
Go to the documentation of this file.
00001 /*
00002  * Setupapi file queue routines
00003  *
00004  * Copyright 2002 Alexandre Julliard for CodeWeavers
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #include "setupapi_private.h"
00022 
00023 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
00024 
00025 /* Unicode constants */
00026 static const WCHAR DotSecurity[]     = {'.','S','e','c','u','r','i','t','y',0};
00027 
00028 /* context structure for the default queue callback */
00029 struct default_callback_context
00030 {
00031     HWND owner;
00032     HWND progress;
00033     UINT message;
00034 };
00035 
00036 struct file_op
00037 {
00038     struct file_op *next;
00039     UINT            style;
00040     WCHAR          *src_root;
00041     WCHAR          *src_path;
00042     WCHAR          *src_file;
00043     WCHAR          *src_descr;
00044     WCHAR          *src_tag;
00045     WCHAR          *dst_path;
00046     WCHAR          *dst_file;
00047     PSECURITY_DESCRIPTOR  dst_sd;
00048 };
00049 
00050 struct file_op_queue
00051 {
00052     struct file_op *head;
00053     struct file_op *tail;
00054     unsigned int count;
00055 };
00056 
00057 struct file_queue
00058 {
00059     struct file_op_queue copy_queue;
00060     struct file_op_queue delete_queue;
00061     struct file_op_queue rename_queue;
00062     DWORD                flags;
00063 };
00064 
00065 
00066 static inline WCHAR *strdupW( const WCHAR *str )
00067 {
00068     WCHAR *ret = NULL;
00069     if (str)
00070     {
00071         int len = (strlenW(str) + 1) * sizeof(WCHAR);
00072         if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) memcpy( ret, str, len );
00073     }
00074     return ret;
00075 }
00076 
00077 static inline char *strdupWtoA( const WCHAR *str )
00078 {
00079     char *ret = NULL;
00080     if (str)
00081     {
00082         DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
00083         if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
00084             WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
00085     }
00086     return ret;
00087 }
00088 
00089 /* append a file operation to a queue */
00090 static inline void queue_file_op( struct file_op_queue *queue, struct file_op *op )
00091 {
00092     op->next = NULL;
00093     if (queue->tail) queue->tail->next = op;
00094     else queue->head = op;
00095     queue->tail = op;
00096     queue->count++;
00097 }
00098 
00099 /* free all the file operations on a given queue */
00100 static void free_file_op_queue( struct file_op_queue *queue )
00101 {
00102     struct file_op *t, *op = queue->head;
00103 
00104     while( op )
00105     {
00106         HeapFree( GetProcessHeap(), 0, op->src_root );
00107         HeapFree( GetProcessHeap(), 0, op->src_path );
00108         HeapFree( GetProcessHeap(), 0, op->src_file );
00109         HeapFree( GetProcessHeap(), 0, op->src_descr );
00110         HeapFree( GetProcessHeap(), 0, op->src_tag );
00111         HeapFree( GetProcessHeap(), 0, op->dst_path );
00112         if (op->dst_sd) LocalFree( op->dst_sd);
00113         if (op->dst_file != op->src_file) HeapFree( GetProcessHeap(), 0, op->dst_file );
00114         t = op;
00115         op = op->next;
00116         HeapFree( GetProcessHeap(), 0, t );
00117     }
00118 }
00119 
00120 /* concat 3 strings to make a path, handling separators correctly */
00121 static void concat_W( WCHAR *buffer, const WCHAR *src1, const WCHAR *src2, const WCHAR *src3 )
00122 {
00123     *buffer = 0;
00124     if (src1 && *src1)
00125     {
00126         strcpyW( buffer, src1 );
00127         buffer += strlenW(buffer );
00128         if (buffer[-1] != '\\') *buffer++ = '\\';
00129         if (src2) while (*src2 == '\\') src2++;
00130     }
00131 
00132     if (src2)
00133     {
00134         strcpyW( buffer, src2 );
00135         buffer += strlenW(buffer );
00136         if (buffer[-1] != '\\') *buffer++ = '\\';
00137         if (src3) while (*src3 == '\\') src3++;
00138     }
00139     if (src3)
00140     {
00141         strcpyW( buffer, src3 );
00142         buffer += strlenW(buffer );
00143     }
00144 }
00145 
00146 
00147 /***********************************************************************
00148  *            build_filepathsW
00149  *
00150  * Build a FILEPATHS_W structure for a given file operation.
00151  */
00152 static BOOL build_filepathsW( const struct file_op *op, FILEPATHS_W *paths )
00153 {
00154     unsigned int src_len = 1, dst_len = 1;
00155     WCHAR *source = (PWSTR)paths->Source, *target = (PWSTR)paths->Target;
00156 
00157     if (op->src_root) src_len += strlenW(op->src_root) + 1;
00158     if (op->src_path) src_len += strlenW(op->src_path) + 1;
00159     if (op->src_file) src_len += strlenW(op->src_file) + 1;
00160     if (op->dst_path) dst_len += strlenW(op->dst_path) + 1;
00161     if (op->dst_file) dst_len += strlenW(op->dst_file) + 1;
00162     src_len *= sizeof(WCHAR);
00163     dst_len *= sizeof(WCHAR);
00164 
00165     if (!source || HeapSize( GetProcessHeap(), 0, source ) < src_len )
00166     {
00167         HeapFree( GetProcessHeap(), 0, source );
00168         paths->Source = source = HeapAlloc( GetProcessHeap(), 0, src_len );
00169     }
00170     if (!target || HeapSize( GetProcessHeap(), 0, target ) < dst_len )
00171     {
00172         HeapFree( GetProcessHeap(), 0, target );
00173         paths->Target = target = HeapAlloc( GetProcessHeap(), 0, dst_len );
00174     }
00175     if (!source || !target) return FALSE;
00176     concat_W( source, op->src_root, op->src_path, op->src_file );
00177     concat_W( target, NULL, op->dst_path, op->dst_file );
00178     paths->Win32Error = 0;
00179     paths->Flags      = 0;
00180     return TRUE;
00181 }
00182 
00183 
00184 /***********************************************************************
00185  *            QUEUE_callback_WtoA
00186  *
00187  * Map a file callback parameters from W to A and call the A callback.
00188  */
00189 UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification,
00190                                    UINT_PTR param1, UINT_PTR param2 )
00191 {
00192     struct callback_WtoA_context *callback_ctx = context;
00193     char buffer[MAX_PATH];
00194     UINT ret;
00195     UINT_PTR old_param2 = param2;
00196 
00197     switch(notification)
00198     {
00199     case SPFILENOTIFY_COPYERROR:
00200         param2 = (UINT_PTR)&buffer;
00201         /* fall through */
00202     case SPFILENOTIFY_STARTDELETE:
00203     case SPFILENOTIFY_ENDDELETE:
00204     case SPFILENOTIFY_DELETEERROR:
00205     case SPFILENOTIFY_STARTRENAME:
00206     case SPFILENOTIFY_ENDRENAME:
00207     case SPFILENOTIFY_RENAMEERROR:
00208     case SPFILENOTIFY_STARTCOPY:
00209     case SPFILENOTIFY_ENDCOPY:
00210     case SPFILENOTIFY_QUEUESCAN_EX:
00211         {
00212             FILEPATHS_W *pathsW = (FILEPATHS_W *)param1;
00213             FILEPATHS_A pathsA;
00214 
00215             pathsA.Source     = strdupWtoA( pathsW->Source );
00216             pathsA.Target     = strdupWtoA( pathsW->Target );
00217             pathsA.Win32Error = pathsW->Win32Error;
00218             pathsA.Flags      = pathsW->Flags;
00219             ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
00220                                               (UINT_PTR)&pathsA, param2 );
00221             HeapFree( GetProcessHeap(), 0, (void *)pathsA.Source );
00222             HeapFree( GetProcessHeap(), 0, (void *)pathsA.Target );
00223         }
00224         if (notification == SPFILENOTIFY_COPYERROR)
00225             MultiByteToWideChar( CP_ACP, 0, buffer, -1, (WCHAR *)old_param2, MAX_PATH );
00226         break;
00227 
00228     case SPFILENOTIFY_STARTREGISTRATION:
00229     case SPFILENOTIFY_ENDREGISTRATION:
00230         {
00231             SP_REGISTER_CONTROL_STATUSW *statusW = (SP_REGISTER_CONTROL_STATUSW *)param1;
00232             SP_REGISTER_CONTROL_STATUSA statusA;
00233 
00234             statusA.cbSize = sizeof(statusA);
00235             statusA.FileName = strdupWtoA( statusW->FileName );
00236             statusA.Win32Error  = statusW->Win32Error;
00237             statusA.FailureCode = statusW->FailureCode;
00238             ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
00239                                               (UINT_PTR)&statusA, param2 );
00240             HeapFree( GetProcessHeap(), 0, (LPSTR)statusA.FileName );
00241         }
00242         break;
00243 
00244     case SPFILENOTIFY_QUEUESCAN:
00245         {
00246             LPWSTR targetW = (LPWSTR)param1;
00247             LPSTR target = strdupWtoA( targetW );
00248 
00249             ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
00250                                               (UINT_PTR)target, param2 );
00251             HeapFree( GetProcessHeap(), 0, target );
00252         }
00253         break;
00254 
00255     case SPFILENOTIFY_NEEDMEDIA:
00256         FIXME("mapping for %d not implemented\n",notification);
00257     case SPFILENOTIFY_STARTQUEUE:
00258     case SPFILENOTIFY_ENDQUEUE:
00259     case SPFILENOTIFY_STARTSUBQUEUE:
00260     case SPFILENOTIFY_ENDSUBQUEUE:
00261     default:
00262         ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, param1, param2 );
00263         break;
00264     }
00265     return ret;
00266 }
00267 
00268 
00269 /***********************************************************************
00270  *            get_src_file_info
00271  *
00272  * Retrieve the source file information for a given file.
00273  */
00274 static void get_src_file_info( HINF hinf, struct file_op *op )
00275 {
00276     static const WCHAR SourceDisksNames[] =
00277         {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s',0};
00278     static const WCHAR SourceDisksFiles[] =
00279         {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0};
00280 
00281     INFCONTEXT file_ctx, disk_ctx;
00282     INT id, diskid;
00283     DWORD len, len2;
00284 
00285     /* find the SourceDisksFiles entry */
00286     if (!SetupFindFirstLineW( hinf, SourceDisksFiles, op->src_file, &file_ctx ))
00287     {
00288         if ((op->style & (SP_COPY_SOURCE_ABSOLUTE|SP_COPY_SOURCEPATH_ABSOLUTE))) return;
00289         /* no specific info, use .inf file source directory */
00290         if (!op->src_root) op->src_root = PARSER_get_src_root( hinf );
00291         return;
00292     }
00293     if (!SetupGetIntField( &file_ctx, 1, &diskid )) return;
00294 
00295     /* now find the diskid in the SourceDisksNames section */
00296     if (!SetupFindFirstLineW( hinf, SourceDisksNames, NULL, &disk_ctx )) return;
00297     for (;;)
00298     {
00299         if (SetupGetIntField( &disk_ctx, 0, &id ) && (id == diskid)) break;
00300         if (!SetupFindNextLine( &disk_ctx, &disk_ctx )) return;
00301     }
00302 
00303     /* and fill in the missing info */
00304 
00305     if (!op->src_descr)
00306     {
00307         if (SetupGetStringFieldW( &disk_ctx, 1, NULL, 0, &len ) &&
00308             (op->src_descr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) )))
00309             SetupGetStringFieldW( &disk_ctx, 1, op->src_descr, len, NULL );
00310     }
00311     if (!op->src_tag)
00312     {
00313         if (SetupGetStringFieldW( &disk_ctx, 2, NULL, 0, &len ) &&
00314             (op->src_tag = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) )))
00315             SetupGetStringFieldW( &disk_ctx, 2, op->src_tag, len, NULL );
00316     }
00317     if (!op->src_path && !(op->style & SP_COPY_SOURCE_ABSOLUTE))
00318     {
00319         len = len2 = 0;
00320         if (!(op->style & SP_COPY_SOURCEPATH_ABSOLUTE))
00321         {
00322             /* retrieve relative path for this disk */
00323             if (!SetupGetStringFieldW( &disk_ctx, 4, NULL, 0, &len )) len = 0;
00324         }
00325         /* retrieve relative path for this file */
00326         if (!SetupGetStringFieldW( &file_ctx, 2, NULL, 0, &len2 )) len2 = 0;
00327 
00328         if ((len || len2) &&
00329             (op->src_path = HeapAlloc( GetProcessHeap(), 0, (len+len2)*sizeof(WCHAR) )))
00330         {
00331             WCHAR *ptr = op->src_path;
00332             if (len)
00333             {
00334                 SetupGetStringFieldW( &disk_ctx, 4, op->src_path, len, NULL );
00335                 ptr = op->src_path + strlenW(op->src_path);
00336                 if (len2 && ptr > op->src_path && ptr[-1] != '\\') *ptr++ = '\\';
00337             }
00338             if (!SetupGetStringFieldW( &file_ctx, 2, ptr, len2, NULL )) *ptr = 0;
00339         }
00340     }
00341     if (!op->src_root) op->src_root = PARSER_get_src_root(hinf);
00342 }
00343 
00344 
00345 /***********************************************************************
00346  *            get_destination_dir
00347  *
00348  * Retrieve the destination dir for a given section.
00349  */
00350 static WCHAR *get_destination_dir( HINF hinf, const WCHAR *section )
00351 {
00352     static const WCHAR Dest[] = {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0};
00353     static const WCHAR Def[]  = {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0};
00354     INFCONTEXT context;
00355 
00356     if (!SetupFindFirstLineW( hinf, Dest, section, &context ) &&
00357         !SetupFindFirstLineW( hinf, Dest, Def, &context )) return NULL;
00358     return PARSER_get_dest_dir( &context );
00359 }
00360 
00361 
00362 static void (WINAPI *pExtractFiles)( LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD );
00363 
00364 /***********************************************************************
00365  *            extract_cabinet_file
00366  *
00367  * Extract a file from a .cab file.
00368  */
00369 static BOOL extract_cabinet_file( const WCHAR *cabinet, const WCHAR *root,
00370                                   const WCHAR *src, const WCHAR *dst )
00371 {
00372     static const WCHAR extW[] = {'.','c','a','b',0};
00373     static HMODULE advpack;
00374 
00375     char *cab_path, *cab_file;
00376     int len = strlenW( cabinet );
00377 
00378     /* make sure the cabinet file has a .cab extension */
00379     if (len <= 4 || strcmpiW( cabinet + len - 4, extW )) return FALSE;
00380     if (!pExtractFiles)
00381     {
00382         if (!advpack && !(advpack = LoadLibraryA( "advpack.dll" )))
00383         {
00384             ERR( "could not load advpack.dll\n" );
00385             return FALSE;
00386         }
00387         if (!(pExtractFiles = (void *)GetProcAddress( advpack, "ExtractFiles" )))
00388         {
00389             ERR( "could not find ExtractFiles in advpack.dll\n" );
00390             return FALSE;
00391         }
00392     }
00393 
00394     if (!(cab_path = strdupWtoA( root ))) return FALSE;
00395     len = WideCharToMultiByte( CP_ACP, 0, cabinet, -1, NULL, 0, NULL, NULL );
00396     if (!(cab_file = HeapAlloc( GetProcessHeap(), 0, strlen(cab_path) + len + 1 )))
00397     {
00398         HeapFree( GetProcessHeap(), 0, cab_path );
00399         return FALSE;
00400     }
00401     strcpy( cab_file, cab_path );
00402     if (cab_file[0] && cab_file[strlen(cab_file)-1] != '\\') strcat( cab_file, "\\" );
00403     WideCharToMultiByte( CP_ACP, 0, cabinet, -1, cab_file + strlen(cab_file), len, NULL, NULL );
00404     FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file) );
00405     pExtractFiles( cab_file, cab_path, 0, 0, 0, 0 );
00406     HeapFree( GetProcessHeap(), 0, cab_file );
00407     HeapFree( GetProcessHeap(), 0, cab_path );
00408     return CopyFileW( src, dst, FALSE /*FIXME*/ );
00409 }
00410 
00411 
00412 /***********************************************************************
00413  *            SetupOpenFileQueue   (SETUPAPI.@)
00414  */
00415 HSPFILEQ WINAPI SetupOpenFileQueue(void)
00416 {
00417     struct file_queue *queue;
00418 
00419     if (!(queue = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*queue))))
00420         return INVALID_HANDLE_VALUE;
00421     return queue;
00422 }
00423 
00424 
00425 /***********************************************************************
00426  *            SetupCloseFileQueue   (SETUPAPI.@)
00427  */
00428 BOOL WINAPI SetupCloseFileQueue( HSPFILEQ handle )
00429 {
00430     struct file_queue *queue = handle;
00431 
00432     free_file_op_queue( &queue->copy_queue );
00433     free_file_op_queue( &queue->rename_queue );
00434     free_file_op_queue( &queue->delete_queue );
00435     HeapFree( GetProcessHeap(), 0, queue );
00436     return TRUE;
00437 }
00438 
00439 
00440 /***********************************************************************
00441  *            SetupQueueCopyIndirectA   (SETUPAPI.@)
00442  */
00443 BOOL WINAPI SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A params )
00444 {
00445     struct file_queue *queue = params->QueueHandle;
00446     struct file_op *op;
00447 
00448     if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
00449     op->style      = params->CopyStyle;
00450     op->src_root   = strdupAtoW( params->SourceRootPath );
00451     op->src_path   = strdupAtoW( params->SourcePath );
00452     op->src_file   = strdupAtoW( params->SourceFilename );
00453     op->src_descr  = strdupAtoW( params->SourceDescription );
00454     op->src_tag    = strdupAtoW( params->SourceTagfile );
00455     op->dst_path   = strdupAtoW( params->TargetDirectory );
00456     op->dst_file   = strdupAtoW( params->TargetFilename );
00457 
00458     /* some defaults */
00459     if (!op->src_file) op->src_file = op->dst_file;
00460     if (params->LayoutInf)
00461     {
00462         get_src_file_info( params->LayoutInf, op );
00463         if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
00464     }
00465 
00466     TRACE( "root=%s path=%s file=%s -> dir=%s file=%s  descr=%s tag=%s\n",
00467            debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
00468            debugstr_w(op->dst_path), debugstr_w(op->dst_file),
00469            debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
00470 
00471     queue_file_op( &queue->copy_queue, op );
00472     return TRUE;
00473 }
00474 
00475 
00476 /***********************************************************************
00477  *            SetupQueueCopyIndirectW   (SETUPAPI.@)
00478  */
00479 BOOL WINAPI SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params )
00480 {
00481     struct file_queue *queue = params->QueueHandle;
00482     struct file_op *op;
00483 
00484     if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
00485     op->style      = params->CopyStyle;
00486     op->src_root   = strdupW( params->SourceRootPath );
00487     op->src_path   = strdupW( params->SourcePath );
00488     op->src_file   = strdupW( params->SourceFilename );
00489     op->src_descr  = strdupW( params->SourceDescription );
00490     op->src_tag    = strdupW( params->SourceTagfile );
00491     op->dst_path   = strdupW( params->TargetDirectory );
00492     op->dst_file   = strdupW( params->TargetFilename );
00493     op->dst_sd     = NULL;
00494     if (params->SecurityDescriptor)
00495         ConvertStringSecurityDescriptorToSecurityDescriptorW( params->SecurityDescriptor, SDDL_REVISION_1, &op->dst_sd, NULL );
00496 
00497     /* some defaults */
00498     if (!op->src_file) op->src_file = op->dst_file;
00499     if (params->LayoutInf)
00500     {
00501         get_src_file_info( params->LayoutInf, op );
00502         if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file );
00503     }
00504 
00505     TRACE( "root=%s path=%s file=%s -> dir=%s file=%s  descr=%s tag=%s\n",
00506            debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file),
00507            debugstr_w(op->dst_path), debugstr_w(op->dst_file),
00508            debugstr_w(op->src_descr), debugstr_w(op->src_tag) );
00509 
00510     queue_file_op( &queue->copy_queue, op );
00511     return TRUE;
00512 }
00513 
00514 
00515 /***********************************************************************
00516  *            SetupQueueCopyA   (SETUPAPI.@)
00517  */
00518 BOOL WINAPI SetupQueueCopyA( HSPFILEQ queue, PCSTR src_root, PCSTR src_path, PCSTR src_file,
00519                              PCSTR src_descr, PCSTR src_tag, PCSTR dst_dir, PCSTR dst_file,
00520                              DWORD style )
00521 {
00522     SP_FILE_COPY_PARAMS_A params;
00523 
00524     params.cbSize             = sizeof(params);
00525     params.QueueHandle        = queue;
00526     params.SourceRootPath     = src_root;
00527     params.SourcePath         = src_path;
00528     params.SourceFilename     = src_file;
00529     params.SourceDescription  = src_descr;
00530     params.SourceTagfile      = src_tag;
00531     params.TargetDirectory    = dst_dir;
00532     params.TargetFilename     = dst_file;
00533     params.CopyStyle          = style;
00534     params.LayoutInf          = 0;
00535     params.SecurityDescriptor = NULL;
00536     return SetupQueueCopyIndirectA( &params );
00537 }
00538 
00539 
00540 /***********************************************************************
00541  *            SetupQueueCopyW   (SETUPAPI.@)
00542  */
00543 BOOL WINAPI SetupQueueCopyW( HSPFILEQ queue, PCWSTR src_root, PCWSTR src_path, PCWSTR src_file,
00544                              PCWSTR src_descr, PCWSTR src_tag, PCWSTR dst_dir, PCWSTR dst_file,
00545                              DWORD style )
00546 {
00547     SP_FILE_COPY_PARAMS_W params;
00548 
00549     params.cbSize             = sizeof(params);
00550     params.QueueHandle        = queue;
00551     params.SourceRootPath     = src_root;
00552     params.SourcePath         = src_path;
00553     params.SourceFilename     = src_file;
00554     params.SourceDescription  = src_descr;
00555     params.SourceTagfile      = src_tag;
00556     params.TargetDirectory    = dst_dir;
00557     params.TargetFilename     = dst_file;
00558     params.CopyStyle          = style;
00559     params.LayoutInf          = 0;
00560     params.SecurityDescriptor = NULL;
00561     return SetupQueueCopyIndirectW( &params );
00562 }
00563 
00564 
00565 /***********************************************************************
00566  *            SetupQueueDefaultCopyA   (SETUPAPI.@)
00567  */
00568 BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ queue, HINF hinf, PCSTR src_root, PCSTR src_file,
00569                                     PCSTR dst_file, DWORD style )
00570 {
00571     SP_FILE_COPY_PARAMS_A params;
00572 
00573     params.cbSize             = sizeof(params);
00574     params.QueueHandle        = queue;
00575     params.SourceRootPath     = src_root;
00576     params.SourcePath         = NULL;
00577     params.SourceFilename     = src_file;
00578     params.SourceDescription  = NULL;
00579     params.SourceTagfile      = NULL;
00580     params.TargetDirectory    = NULL;
00581     params.TargetFilename     = dst_file;
00582     params.CopyStyle          = style;
00583     params.LayoutInf          = hinf;
00584     params.SecurityDescriptor = NULL;
00585     return SetupQueueCopyIndirectA( &params );
00586 }
00587 
00588 
00589 /***********************************************************************
00590  *            SetupQueueDefaultCopyW   (SETUPAPI.@)
00591  */
00592 BOOL WINAPI SetupQueueDefaultCopyW( HSPFILEQ queue, HINF hinf, PCWSTR src_root, PCWSTR src_file,
00593                                     PCWSTR dst_file, DWORD style )
00594 {
00595     SP_FILE_COPY_PARAMS_W params;
00596 
00597     params.cbSize             = sizeof(params);
00598     params.QueueHandle        = queue;
00599     params.SourceRootPath     = src_root;
00600     params.SourcePath         = NULL;
00601     params.SourceFilename     = src_file;
00602     params.SourceDescription  = NULL;
00603     params.SourceTagfile      = NULL;
00604     params.TargetDirectory    = NULL;
00605     params.TargetFilename     = dst_file;
00606     params.CopyStyle          = style;
00607     params.LayoutInf          = hinf;
00608     params.SecurityDescriptor = NULL;
00609     return SetupQueueCopyIndirectW( &params );
00610 }
00611 
00612 
00613 /***********************************************************************
00614  *            SetupQueueDeleteA   (SETUPAPI.@)
00615  */
00616 BOOL WINAPI SetupQueueDeleteA( HSPFILEQ handle, PCSTR part1, PCSTR part2 )
00617 {
00618     struct file_queue *queue = handle;
00619     struct file_op *op;
00620 
00621     if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
00622     op->style      = 0;
00623     op->src_root   = NULL;
00624     op->src_path   = NULL;
00625     op->src_file   = NULL;
00626     op->src_descr  = NULL;
00627     op->src_tag    = NULL;
00628     op->dst_path   = strdupAtoW( part1 );
00629     op->dst_file   = strdupAtoW( part2 );
00630     queue_file_op( &queue->delete_queue, op );
00631     return TRUE;
00632 }
00633 
00634 
00635 /***********************************************************************
00636  *            SetupQueueDeleteW   (SETUPAPI.@)
00637  */
00638 BOOL WINAPI SetupQueueDeleteW( HSPFILEQ handle, PCWSTR part1, PCWSTR part2 )
00639 {
00640     struct file_queue *queue = handle;
00641     struct file_op *op;
00642 
00643     if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
00644     op->style      = 0;
00645     op->src_root   = NULL;
00646     op->src_path   = NULL;
00647     op->src_file   = NULL;
00648     op->src_descr  = NULL;
00649     op->src_tag    = NULL;
00650     op->dst_path   = strdupW( part1 );
00651     op->dst_file   = strdupW( part2 );
00652     queue_file_op( &queue->delete_queue, op );
00653     return TRUE;
00654 }
00655 
00656 
00657 /***********************************************************************
00658  *            SetupQueueRenameA   (SETUPAPI.@)
00659  */
00660 BOOL WINAPI SetupQueueRenameA( HSPFILEQ handle, PCSTR SourcePath, PCSTR SourceFilename,
00661                                PCSTR TargetPath, PCSTR TargetFilename )
00662 {
00663     struct file_queue *queue = handle;
00664     struct file_op *op;
00665 
00666     if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
00667     op->style      = 0;
00668     op->src_root   = NULL;
00669     op->src_path   = strdupAtoW( SourcePath );
00670     op->src_file   = strdupAtoW( SourceFilename );
00671     op->src_descr  = NULL;
00672     op->src_tag    = NULL;
00673     op->dst_path   = strdupAtoW( TargetPath );
00674     op->dst_file   = strdupAtoW( TargetFilename );
00675     queue_file_op( &queue->rename_queue, op );
00676     return TRUE;
00677 }
00678 
00679 
00680 /***********************************************************************
00681  *            SetupQueueRenameW   (SETUPAPI.@)
00682  */
00683 BOOL WINAPI SetupQueueRenameW( HSPFILEQ handle, PCWSTR SourcePath, PCWSTR SourceFilename,
00684                                PCWSTR TargetPath, PCWSTR TargetFilename )
00685 {
00686     struct file_queue *queue = handle;
00687     struct file_op *op;
00688 
00689     if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE;
00690     op->style      = 0;
00691     op->src_root   = NULL;
00692     op->src_path   = strdupW( SourcePath );
00693     op->src_file   = strdupW( SourceFilename );
00694     op->src_descr  = NULL;
00695     op->src_tag    = NULL;
00696     op->dst_path   = strdupW( TargetPath );
00697     op->dst_file   = strdupW( TargetFilename );
00698     queue_file_op( &queue->rename_queue, op );
00699     return TRUE;
00700 }
00701 
00702 
00703 /***********************************************************************
00704  *            SetupQueueCopySectionA   (SETUPAPI.@)
00705  */
00706 BOOL WINAPI SetupQueueCopySectionA( HSPFILEQ queue, PCSTR src_root, HINF hinf, HINF hlist,
00707                                     PCSTR section, DWORD style )
00708 {
00709     UNICODE_STRING sectionW;
00710     BOOL ret = FALSE;
00711 
00712     if (!RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
00713     {
00714         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
00715         return FALSE;
00716     }
00717     if (!src_root)
00718         ret = SetupQueueCopySectionW( queue, NULL, hinf, hlist, sectionW.Buffer, style );
00719     else
00720     {
00721         UNICODE_STRING srcW;
00722         if (RtlCreateUnicodeStringFromAsciiz( &srcW, src_root ))
00723         {
00724             ret = SetupQueueCopySectionW( queue, srcW.Buffer, hinf, hlist, sectionW.Buffer, style );
00725             RtlFreeUnicodeString( &srcW );
00726         }
00727         else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
00728     }
00729     RtlFreeUnicodeString( &sectionW );
00730     return ret;
00731 }
00732 
00733 
00734 /***********************************************************************
00735  *            SetupQueueCopySectionW   (SETUPAPI.@)
00736  */
00737 BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ queue, PCWSTR src_root, HINF hinf, HINF hlist,
00738                                     PCWSTR section, DWORD style )
00739 {
00740     SP_FILE_COPY_PARAMS_W params;
00741     LPWSTR security_key, security_descriptor = NULL;
00742     INFCONTEXT context, security_context;
00743     WCHAR dest[MAX_PATH], src[MAX_PATH];
00744     INT flags;
00745     DWORD required;
00746     BOOL ret;
00747 
00748     TRACE( "hinf=%p/%p section=%s root=%s\n",
00749            hinf, hlist, debugstr_w(section), debugstr_w(src_root) );
00750 
00751     /* Check for .Security section */
00752     security_key = MyMalloc( (strlenW( section ) + strlenW( DotSecurity )) * sizeof(WCHAR) + sizeof(UNICODE_NULL) );
00753     if (!security_key)
00754     {
00755         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00756         return FALSE;
00757     }
00758     strcpyW( security_key, section );
00759     strcatW( security_key, DotSecurity );
00760     ret = SetupFindFirstLineW( hinf, security_key, NULL, &security_context );
00761     MyFree(security_key);
00762     if (ret)
00763     {
00764         if (!SetupGetLineTextW( &security_context, NULL, NULL, NULL, NULL, 0, &required ))
00765             return FALSE;
00766         security_descriptor = MyMalloc( required * sizeof(WCHAR) );
00767         if (!security_descriptor)
00768         {
00769             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00770             return FALSE;
00771         }
00772         if (!SetupGetLineTextW( &security_context, NULL, NULL, NULL, security_descriptor, required, NULL ))
00773         {
00774             MyFree( security_descriptor );
00775             return FALSE;
00776         }
00777     }
00778 
00779     params.cbSize             = sizeof(params);
00780     params.QueueHandle        = queue;
00781     params.SourceRootPath     = src_root;
00782     params.SourcePath         = NULL;
00783     params.SourceDescription  = NULL;
00784     params.SourceTagfile      = NULL;
00785     params.TargetFilename     = dest;
00786     params.CopyStyle          = style;
00787     params.LayoutInf          = hinf;
00788     params.SecurityDescriptor = security_descriptor;
00789 
00790     ret = FALSE;
00791     if (!hlist) hlist = hinf;
00792     if (!hinf) hinf = hlist;
00793     if (!SetupFindFirstLineW( hlist, section, NULL, &context )) goto done;
00794     if (!(params.TargetDirectory = get_destination_dir( hinf, section ))) goto done;
00795     do
00796     {
00797         if (!SetupGetStringFieldW( &context, 1, dest, sizeof(dest)/sizeof(WCHAR), NULL ))
00798             goto done;
00799         if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL )) *src = 0;
00800         if (!SetupGetIntField( &context, 4, &flags )) flags = 0;  /* FIXME */
00801 
00802         params.SourceFilename = *src ? src : NULL;
00803         if (!SetupQueueCopyIndirectW( &params )) goto done;
00804     } while (SetupFindNextLine( &context, &context ));
00805     ret = TRUE;
00806 
00807 done:
00808     if (security_descriptor)
00809         MyFree( security_descriptor );
00810     return ret;
00811 }
00812 
00813 
00814 /***********************************************************************
00815  *            SetupQueueDeleteSectionA   (SETUPAPI.@)
00816  */
00817 BOOL WINAPI SetupQueueDeleteSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
00818 {
00819     UNICODE_STRING sectionW;
00820     BOOL ret = FALSE;
00821 
00822     if (RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
00823     {
00824         ret = SetupQueueDeleteSectionW( queue, hinf, hlist, sectionW.Buffer );
00825         RtlFreeUnicodeString( &sectionW );
00826     }
00827     else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
00828     return ret;
00829 }
00830 
00831 
00832 /***********************************************************************
00833  *            SetupQueueDeleteSectionW   (SETUPAPI.@)
00834  */
00835 BOOL WINAPI SetupQueueDeleteSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
00836 {
00837     INFCONTEXT context;
00838     WCHAR *dest_dir;
00839     WCHAR buffer[MAX_PATH];
00840     BOOL ret = FALSE;
00841     INT flags;
00842 
00843     TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
00844 
00845     if (!hlist) hlist = hinf;
00846     if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
00847     if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
00848     do
00849     {
00850         if (!SetupGetStringFieldW( &context, 1, buffer, sizeof(buffer)/sizeof(WCHAR), NULL ))
00851             goto done;
00852         if (!SetupGetIntField( &context, 4, &flags )) flags = 0;
00853         if (!SetupQueueDeleteW( queue, dest_dir, buffer )) goto done;
00854     } while (SetupFindNextLine( &context, &context ));
00855 
00856     ret = TRUE;
00857  done:
00858     HeapFree( GetProcessHeap(), 0, dest_dir );
00859     return ret;
00860 }
00861 
00862 
00863 /***********************************************************************
00864  *            SetupQueueRenameSectionA   (SETUPAPI.@)
00865  */
00866 BOOL WINAPI SetupQueueRenameSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section )
00867 {
00868     UNICODE_STRING sectionW;
00869     BOOL ret = FALSE;
00870 
00871     if (RtlCreateUnicodeStringFromAsciiz( &sectionW, section ))
00872     {
00873         ret = SetupQueueRenameSectionW( queue, hinf, hlist, sectionW.Buffer );
00874         RtlFreeUnicodeString( &sectionW );
00875     }
00876     else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
00877     return ret;
00878 }
00879 
00880 
00881 /***********************************************************************
00882  *            SetupQueueRenameSectionW   (SETUPAPI.@)
00883  */
00884 BOOL WINAPI SetupQueueRenameSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section )
00885 {
00886     INFCONTEXT context;
00887     WCHAR *dest_dir;
00888     WCHAR src[MAX_PATH], dst[MAX_PATH];
00889     BOOL ret = FALSE;
00890 
00891     TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) );
00892 
00893     if (!hlist) hlist = hinf;
00894     if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE;
00895     if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE;
00896     do
00897     {
00898         if (!SetupGetStringFieldW( &context, 1, dst, sizeof(dst)/sizeof(WCHAR), NULL ))
00899             goto done;
00900         if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL ))
00901             goto done;
00902         if (!SetupQueueRenameW( queue, dest_dir, src, NULL, dst )) goto done;
00903     } while (SetupFindNextLine( &context, &context ));
00904 
00905     ret = TRUE;
00906  done:
00907     HeapFree( GetProcessHeap(), 0, dest_dir );
00908     return ret;
00909 }
00910 
00911 
00912 /***********************************************************************
00913  *            SetupCommitFileQueueA   (SETUPAPI.@)
00914  */
00915 BOOL WINAPI SetupCommitFileQueueA( HWND owner, HSPFILEQ queue, PSP_FILE_CALLBACK_A handler,
00916                                    PVOID context )
00917 {
00918     struct callback_WtoA_context ctx;
00919 
00920     ctx.orig_context = context;
00921     ctx.orig_handler = handler;
00922     return SetupCommitFileQueueW( owner, queue, QUEUE_callback_WtoA, &ctx );
00923 }
00924 
00925 
00926 /***********************************************************************
00927  *            create_full_pathW
00928  *
00929  * Recursively create all directories in the path.
00930  */
00931 static BOOL create_full_pathW(const WCHAR *path)
00932 {
00933     BOOL ret = TRUE;
00934     int len;
00935     WCHAR *new_path;
00936 
00937     new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * sizeof(WCHAR));
00938     strcpyW(new_path, path);
00939 
00940     while((len = strlenW(new_path)) && new_path[len - 1] == '\\')
00941         new_path[len - 1] = 0;
00942 
00943     while(!CreateDirectoryW(new_path, NULL))
00944     {
00945         WCHAR *slash;
00946         DWORD last_error = GetLastError();
00947 
00948         if(last_error == ERROR_ALREADY_EXISTS)
00949             break;
00950 
00951         if(last_error != ERROR_PATH_NOT_FOUND)
00952         {
00953             ret = FALSE;
00954             break;
00955         }
00956 
00957         if(!(slash = strrchrW(new_path, '\\')))
00958         {
00959             ret = FALSE;
00960             break;
00961         }
00962 
00963         len = slash - new_path;
00964         new_path[len] = 0;
00965         if(!create_full_pathW(new_path))
00966         {
00967             ret = FALSE;
00968             break;
00969         }
00970         new_path[len] = '\\';
00971     }
00972 
00973     HeapFree(GetProcessHeap(), 0, new_path);
00974     return ret;
00975 }
00976 
00977 static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style,
00978                            PSP_FILE_CALLBACK_W handler, PVOID context )
00979 {
00980     BOOL rc = FALSE;
00981     BOOL docopy = TRUE;
00982 
00983     TRACE("copy %s to %s style 0x%x\n",debugstr_w(source),debugstr_w(target),style);
00984 
00985     /* before copy processing */
00986     if (style & SP_COPY_REPLACEONLY)
00987     {
00988         if (GetFileAttributesW(target) == INVALID_FILE_ATTRIBUTES)
00989             docopy = FALSE;
00990     }
00991     if (style & (SP_COPY_NEWER_OR_SAME | SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER))
00992     {
00993         DWORD VersionSizeSource=0;
00994         DWORD VersionSizeTarget=0;
00995         DWORD zero=0;
00996 
00997         /*
00998          * This is sort of an interesting workaround. You see, calling
00999          * GetVersionInfoSize on a builtin dll loads that dll into memory
01000          * and we do not properly unload builtin dlls.. so we effectively
01001          * lock into memory all the targets we are replacing. This leads
01002          * to problems when we try to register the replaced dlls.
01003          *
01004          * So I will test for the existence of the files first so that
01005          * we just basically unconditionally replace the builtin versions.
01006          */
01007         if ((GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) &&
01008             (GetFileAttributesW(source) != INVALID_FILE_ATTRIBUTES))
01009         {
01010             VersionSizeSource = GetFileVersionInfoSizeW((LPWSTR)source,&zero);
01011             VersionSizeTarget = GetFileVersionInfoSizeW((LPWSTR)target,&zero);
01012         }
01013 
01014         TRACE("SizeTarget %i ... SizeSource %i\n",VersionSizeTarget,
01015                 VersionSizeSource);
01016 
01017         if (VersionSizeSource && VersionSizeTarget)
01018         {
01019             LPVOID VersionSource;
01020             LPVOID VersionTarget;
01021             VS_FIXEDFILEINFO *TargetInfo;
01022             VS_FIXEDFILEINFO *SourceInfo;
01023             UINT length;
01024             WCHAR  SubBlock[2]={'\\',0};
01025             DWORD  ret;
01026 
01027             VersionSource = HeapAlloc(GetProcessHeap(),0,VersionSizeSource);
01028             VersionTarget = HeapAlloc(GetProcessHeap(),0,VersionSizeTarget);
01029 
01030             ret = GetFileVersionInfoW((LPWSTR)source,0,VersionSizeSource,VersionSource);
01031             if (ret)
01032               ret = GetFileVersionInfoW((LPWSTR)target, 0, VersionSizeTarget,
01033                     VersionTarget);
01034 
01035             if (ret)
01036             {
01037                 ret = VerQueryValueW(VersionSource, SubBlock,
01038                                     (LPVOID*)&SourceInfo, &length);
01039                 if (ret)
01040                     ret = VerQueryValueW(VersionTarget, SubBlock,
01041                                          (LPVOID*)&TargetInfo, &length);
01042 
01043                 if (ret)
01044                 {
01045                     FILEPATHS_W filepaths;
01046 
01047                     TRACE("Versions: Source %i.%i target %i.%i\n",
01048                       SourceInfo->dwFileVersionMS, SourceInfo->dwFileVersionLS,
01049                       TargetInfo->dwFileVersionMS, TargetInfo->dwFileVersionLS);
01050 
01051                     /* used in case of notification */
01052                     filepaths.Target = target;
01053                     filepaths.Source = source;
01054                     filepaths.Win32Error = 0;
01055                     filepaths.Flags = 0;
01056 
01057                     if (TargetInfo->dwFileVersionMS > SourceInfo->dwFileVersionMS)
01058                     {
01059                         if (handler)
01060                             docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
01061                         else
01062                             docopy = FALSE;
01063                     }
01064                     else if ((TargetInfo->dwFileVersionMS == SourceInfo->dwFileVersionMS)
01065                              && (TargetInfo->dwFileVersionLS > SourceInfo->dwFileVersionLS))
01066                     {
01067                         if (handler)
01068                             docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
01069                         else
01070                             docopy = FALSE;
01071                     }
01072                     else if ((style & SP_COPY_NEWER_ONLY) &&
01073                         (TargetInfo->dwFileVersionMS ==
01074                          SourceInfo->dwFileVersionMS)
01075                         &&(TargetInfo->dwFileVersionLS ==
01076                         SourceInfo->dwFileVersionLS))
01077                     {
01078                         if (handler)
01079                             docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0);
01080                         else
01081                             docopy = FALSE;
01082                     }
01083                 }
01084             }
01085             HeapFree(GetProcessHeap(),0,VersionSource);
01086             HeapFree(GetProcessHeap(),0,VersionTarget);
01087         }
01088     }
01089     if (style & (SP_COPY_NOOVERWRITE | SP_COPY_FORCE_NOOVERWRITE))
01090     {
01091         if (GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES)
01092         {
01093             FIXME("Notify user target file exists\n");
01094             docopy = FALSE;
01095         }
01096     }
01097     if (style & (SP_COPY_NODECOMP | SP_COPY_LANGUAGEAWARE | SP_COPY_FORCE_IN_USE |
01098                  SP_COPY_IN_USE_NEEDS_REBOOT | SP_COPY_NOSKIP | SP_COPY_WARNIFSKIP))
01099     {
01100         ERR("Unsupported style(s) 0x%x\n",style);
01101     }
01102 
01103     if (docopy)
01104     {
01105         rc = CopyFileW(source,target,FALSE);
01106         TRACE("Did copy... rc was %i\n",rc);
01107     }
01108 
01109     /* after copy processing */
01110     if (style & SP_COPY_DELETESOURCE)
01111     {
01112        if (rc)
01113             DeleteFileW(source);
01114     }
01115 
01116     return rc;
01117 }
01118 
01119 /***********************************************************************
01120  *            SetupInstallFileA   (SETUPAPI.@)
01121  */
01122 BOOL WINAPI SetupInstallFileA( HINF hinf, PINFCONTEXT inf_context, PCSTR source, PCSTR root,
01123                                PCSTR dest, DWORD style, PSP_FILE_CALLBACK_A handler, PVOID context )
01124 {
01125     BOOL ret = FALSE;
01126     struct callback_WtoA_context ctx;
01127     UNICODE_STRING sourceW, rootW, destW;
01128 
01129     TRACE("%p %p %s %s %s %x %p %p\n", hinf, inf_context, debugstr_a(source), debugstr_a(root),
01130           debugstr_a(dest), style, handler, context);
01131 
01132     sourceW.Buffer = rootW.Buffer = destW.Buffer = NULL;
01133     if (source && !RtlCreateUnicodeStringFromAsciiz( &sourceW, source ))
01134     {
01135         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
01136         return FALSE;
01137     }
01138     if (root && !RtlCreateUnicodeStringFromAsciiz( &rootW, root ))
01139     {
01140         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
01141         goto exit;
01142     }
01143     if (dest && !RtlCreateUnicodeStringFromAsciiz( &destW, dest ))
01144     {
01145         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
01146         goto exit;
01147     }
01148 
01149     ctx.orig_context = context;
01150     ctx.orig_handler = handler;
01151 
01152     ret = SetupInstallFileW( hinf, inf_context, sourceW.Buffer, rootW.Buffer, destW.Buffer, style, QUEUE_callback_WtoA, &ctx );
01153 
01154 exit:
01155     RtlFreeUnicodeString( &sourceW );
01156     RtlFreeUnicodeString( &rootW );
01157     RtlFreeUnicodeString( &destW );
01158     return ret;
01159 }
01160 
01161 /***********************************************************************
01162  *            SetupInstallFileW   (SETUPAPI.@)
01163  */
01164 BOOL WINAPI SetupInstallFileW( HINF hinf, PINFCONTEXT inf_context, PCWSTR source, PCWSTR root,
01165                                PCWSTR dest, DWORD style, PSP_FILE_CALLBACK_W handler, PVOID context )
01166 {
01167     static const WCHAR CopyFiles[] = {'C','o','p','y','F','i','l','e','s',0};
01168 
01169     BOOL ret, absolute = (root && *root && !(style & SP_COPY_SOURCE_ABSOLUTE));
01170     WCHAR *buffer, *p, *inf_source = NULL;
01171     unsigned int len;
01172 
01173     TRACE("%p %p %s %s %s %x %p %p\n", hinf, inf_context, debugstr_w(source), debugstr_w(root),
01174           debugstr_w(dest), style, handler, context);
01175 
01176     if (hinf)
01177     {
01178         INFCONTEXT ctx;
01179 
01180         if (!inf_context)
01181         {
01182             inf_context = &ctx;
01183             if (!SetupFindFirstLineW( hinf, CopyFiles, NULL, inf_context )) return FALSE;
01184         }
01185         if (!SetupGetStringFieldW( inf_context, 1, NULL, 0, (PDWORD) &len )) return FALSE;
01186         if (!(inf_source = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
01187         {
01188             SetLastError( ERROR_NOT_ENOUGH_MEMORY );
01189             return FALSE;
01190         }
01191         if (!SetupGetStringFieldW( inf_context, 1, inf_source, len, NULL )) return FALSE;
01192         source = inf_source;
01193     }
01194     else if (!source)
01195     {
01196         SetLastError( ERROR_INVALID_PARAMETER );
01197         return FALSE;
01198     }
01199 
01200     len = strlenW( source ) + 1;
01201     if (absolute) len += strlenW( root ) + 1;
01202 
01203     if (!(p = buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
01204     {
01205         HeapFree( GetProcessHeap(), 0, inf_source );
01206         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
01207         return FALSE;
01208     }
01209 
01210     if (absolute)
01211     {
01212         strcpyW( buffer, root );
01213         p += strlenW( buffer );
01214         if (p[-1] != '\\') *p++ = '\\';
01215     }
01216     while (*source == '\\') source++;
01217     strcpyW( p, source );
01218 
01219     ret = do_file_copyW( buffer, dest, style, handler, context );
01220 
01221     HeapFree( GetProcessHeap(), 0, inf_source );
01222     HeapFree( GetProcessHeap(), 0, buffer );
01223     return ret;
01224 }
01225 
01226 /***********************************************************************
01227  *            SetupCommitFileQueueW   (SETUPAPI.@)
01228  */
01229 BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBACK_W handler,
01230                                    PVOID context )
01231 {
01232     struct file_queue *queue = handle;
01233     struct file_op *op;
01234     BOOL result = FALSE;
01235     FILEPATHS_W paths;
01236     UINT op_result;
01237 
01238     paths.Source = paths.Target = NULL;
01239 
01240     if (!queue->copy_queue.count && !queue->delete_queue.count && !queue->rename_queue.count)
01241         return TRUE;  /* nothing to do */
01242 
01243     if (!handler( context, SPFILENOTIFY_STARTQUEUE, (UINT_PTR)owner, 0 )) return FALSE;
01244 
01245     /* perform deletes */
01246 
01247     if (queue->delete_queue.count)
01248     {
01249         if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_DELETE,
01250                        queue->delete_queue.count ))) goto done;
01251         for (op = queue->delete_queue.head; op; op = op->next)
01252         {
01253             build_filepathsW( op, &paths );
01254             op_result = handler( context, SPFILENOTIFY_STARTDELETE, (UINT_PTR)&paths, FILEOP_DELETE);
01255             if (op_result == FILEOP_ABORT) goto done;
01256             while (op_result == FILEOP_DOIT)
01257             {
01258                 TRACE( "deleting file %s\n", debugstr_w(paths.Target) );
01259                 if (DeleteFileW( paths.Target )) break;  /* success */
01260                 paths.Win32Error = GetLastError();
01261                 op_result = handler( context, SPFILENOTIFY_DELETEERROR, (UINT_PTR)&paths, 0 );
01262                 if (op_result == FILEOP_ABORT) goto done;
01263             }
01264             handler( context, SPFILENOTIFY_ENDDELETE, (UINT_PTR)&paths, 0 );
01265         }
01266         handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_DELETE, 0 );
01267     }
01268 
01269     /* perform renames */
01270 
01271     if (queue->rename_queue.count)
01272     {
01273         if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_RENAME,
01274                        queue->rename_queue.count ))) goto done;
01275         for (op = queue->rename_queue.head; op; op = op->next)
01276         {
01277             build_filepathsW( op, &paths );
01278             op_result = handler( context, SPFILENOTIFY_STARTRENAME, (UINT_PTR)&paths, FILEOP_RENAME);
01279             if (op_result == FILEOP_ABORT) goto done;
01280             while (op_result == FILEOP_DOIT)
01281             {
01282                 TRACE( "renaming file %s -> %s\n",
01283                        debugstr_w(paths.Source), debugstr_w(paths.Target) );
01284                 if (MoveFileW( paths.Source, paths.Target )) break;  /* success */
01285                 paths.Win32Error = GetLastError();
01286                 op_result = handler( context, SPFILENOTIFY_RENAMEERROR, (UINT_PTR)&paths, 0 );
01287                 if (op_result == FILEOP_ABORT) goto done;
01288             }
01289             handler( context, SPFILENOTIFY_ENDRENAME, (UINT_PTR)&paths, 0 );
01290         }
01291         handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_RENAME, 0 );
01292     }
01293 
01294     /* perform copies */
01295 
01296     if (queue->copy_queue.count)
01297     {
01298         if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_COPY,
01299                        queue->copy_queue.count ))) goto done;
01300         for (op = queue->copy_queue.head; op; op = op->next)
01301         {
01302             WCHAR newpath[MAX_PATH];
01303 
01304             build_filepathsW( op, &paths );
01305             op_result = handler( context, SPFILENOTIFY_STARTCOPY, (UINT_PTR)&paths, FILEOP_COPY );
01306             if (op_result == FILEOP_ABORT) goto done;
01307             if (op_result == FILEOP_NEWPATH) op_result = FILEOP_DOIT;
01308             while (op_result == FILEOP_DOIT || op_result == FILEOP_NEWPATH)
01309             {
01310                 TRACE( "copying file %s -> %s\n",
01311                        debugstr_w( op_result == FILEOP_NEWPATH ? newpath : paths.Source ),
01312                        debugstr_w(paths.Target) );
01313                 if (op->dst_path)
01314                 {
01315                     if (!create_full_pathW( op->dst_path ))
01316                     {
01317                         paths.Win32Error = GetLastError();
01318                         op_result = handler( context, SPFILENOTIFY_COPYERROR,
01319                                      (UINT_PTR)&paths, (UINT_PTR)newpath );
01320                         if (op_result == FILEOP_ABORT) goto done;
01321                     }
01322                 }
01323                 if (do_file_copyW( op_result == FILEOP_NEWPATH ? newpath : paths.Source,
01324                                paths.Target, op->style, handler, context )) break;  /* success */
01325                 /* try to extract it from the cabinet file */
01326                 if (op->src_tag)
01327                 {
01328                     if (extract_cabinet_file( op->src_tag, op->src_root,
01329                                               paths.Source, paths.Target )) break;
01330                 }
01331                 paths.Win32Error = GetLastError();
01332                 op_result = handler( context, SPFILENOTIFY_COPYERROR,
01333                                      (UINT_PTR)&paths, (UINT_PTR)newpath );
01334                 if (op_result == FILEOP_ABORT) goto done;
01335             }
01336             if (op->dst_sd)
01337             {
01338                 PSID psidOwner = NULL, psidGroup = NULL;
01339                 PACL pDacl = NULL, pSacl = NULL;
01340                 SECURITY_INFORMATION security_info = 0;
01341                 BOOL present, dummy;
01342 
01343                 if (GetSecurityDescriptorOwner( op->dst_sd, &psidOwner, &dummy ) && psidOwner)
01344                     security_info |= OWNER_SECURITY_INFORMATION;
01345                 if (GetSecurityDescriptorGroup( op->dst_sd, &psidGroup, &dummy ) && psidGroup)
01346                     security_info |= GROUP_SECURITY_INFORMATION;
01347                 if (GetSecurityDescriptorDacl( op->dst_sd, &present, &pDacl, &dummy ))
01348                     security_info |= DACL_SECURITY_INFORMATION;
01349                 if (GetSecurityDescriptorSacl( op->dst_sd, &present, &pSacl, &dummy ))
01350                     security_info |= DACL_SECURITY_INFORMATION;
01351                 SetNamedSecurityInfoW( (LPWSTR)paths.Target, SE_FILE_OBJECT, security_info,
01352                     psidOwner, psidGroup, pDacl, pSacl );
01353                 /* Yes, ignore the return code... */
01354             }
01355             handler( context, SPFILENOTIFY_ENDCOPY, (UINT_PTR)&paths, 0 );
01356         }
01357         handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_COPY, 0 );
01358     }
01359 
01360 
01361     result = TRUE;
01362 
01363  done:
01364     handler( context, SPFILENOTIFY_ENDQUEUE, result, 0 );
01365     HeapFree( GetProcessHeap(), 0, (void *)paths.Source );
01366     HeapFree( GetProcessHeap(), 0, (void *)paths.Target );
01367     return result;
01368 }
01369 
01370 
01371 /***********************************************************************
01372  *            SetupScanFileQueueA   (SETUPAPI.@)
01373  */
01374 BOOL WINAPI SetupScanFileQueueA( HSPFILEQ handle, DWORD flags, HWND window,
01375                                  PSP_FILE_CALLBACK_A handler, PVOID context, PDWORD result )
01376 {
01377     struct callback_WtoA_context ctx;
01378 
01379     TRACE("%p %x %p %p %p %p\n", handle, flags, window, handler, context, result);
01380 
01381     ctx.orig_context = context;
01382     ctx.orig_handler = handler;
01383 
01384     return SetupScanFileQueueW( handle, flags, window, QUEUE_callback_WtoA, &ctx, result );
01385 }
01386 
01387 
01388 /***********************************************************************
01389  *            SetupScanFileQueueW   (SETUPAPI.@)
01390  */
01391 BOOL WINAPI SetupScanFileQueueW( HSPFILEQ handle, DWORD flags, HWND window,
01392                                  PSP_FILE_CALLBACK_W handler, PVOID context, PDWORD result )
01393 {
01394     struct file_queue *queue = handle;
01395     struct file_op *op;
01396     FILEPATHS_W paths;
01397     UINT notification = 0;
01398     BOOL ret = FALSE;
01399 
01400     TRACE("%p %x %p %p %p %p\n", handle, flags, window, handler, context, result);
01401 
01402     *result = FALSE;
01403 
01404     if (!queue->copy_queue.count) return TRUE;
01405 
01406     if (flags & SPQ_SCAN_USE_CALLBACK)        notification = SPFILENOTIFY_QUEUESCAN;
01407     else if (flags & SPQ_SCAN_USE_CALLBACKEX) notification = SPFILENOTIFY_QUEUESCAN_EX;
01408 
01409     if (flags & ~(SPQ_SCAN_USE_CALLBACK | SPQ_SCAN_USE_CALLBACKEX))
01410     {
01411         FIXME("flags %x not fully implemented\n", flags);
01412     }
01413 
01414     paths.Source = paths.Target = NULL;
01415 
01416     for (op = queue->copy_queue.head; op; op = op->next)
01417     {
01418         build_filepathsW( op, &paths );
01419         switch (notification)
01420         {
01421         case SPFILENOTIFY_QUEUESCAN:
01422             /* FIXME: handle delay flag */
01423             if (handler( context,  notification, (UINT_PTR)paths.Target, 0 )) goto done;
01424             break;
01425         case SPFILENOTIFY_QUEUESCAN_EX:
01426             if (handler( context, notification, (UINT_PTR)&paths, 0 )) goto done;
01427             break;
01428         default:
01429             ret = TRUE; goto done;
01430         }
01431     }
01432 
01433     *result = TRUE;
01434 
01435  done:
01436     HeapFree( GetProcessHeap(), 0, (void *)paths.Source );
01437     HeapFree( GetProcessHeap(), 0, (void *)paths.Target );
01438     return ret;
01439 }
01440 
01441 
01442 /***********************************************************************
01443  *            SetupGetFileQueueCount   (SETUPAPI.@)
01444  */
01445 BOOL WINAPI SetupGetFileQueueCount( HSPFILEQ handle, UINT op, PUINT result )
01446 {
01447     struct file_queue *queue = handle;
01448 
01449     switch(op)
01450     {
01451     case FILEOP_COPY:
01452         *result = queue->copy_queue.count;
01453         return TRUE;
01454     case FILEOP_RENAME:
01455         *result = queue->rename_queue.count;
01456         return TRUE;
01457     case FILEOP_DELETE:
01458         *result = queue->delete_queue.count;
01459         return TRUE;
01460     }
01461     return FALSE;
01462 }
01463 
01464 
01465 /***********************************************************************
01466  *            SetupGetFileQueueFlags   (SETUPAPI.@)
01467  */
01468 BOOL WINAPI SetupGetFileQueueFlags( HSPFILEQ handle, PDWORD flags )
01469 {
01470     struct file_queue *queue = handle;
01471     *flags = queue->flags;
01472     return TRUE;
01473 }
01474 
01475 
01476 /***********************************************************************
01477  *            SetupSetFileQueueFlags   (SETUPAPI.@)
01478  */
01479 BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ handle, DWORD mask, DWORD flags )
01480 {
01481     struct file_queue *queue = handle;
01482     queue->flags = (queue->flags & ~mask) | flags;
01483     return TRUE;
01484 }
01485 
01486 
01487 /***********************************************************************
01488  *   SetupSetFileQueueAlternatePlatformA  (SETUPAPI.@)
01489  */
01490 BOOL WINAPI SetupSetFileQueueAlternatePlatformA(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCSTR catalogfile)
01491 {
01492     FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_a(catalogfile));
01493     return FALSE;
01494 }
01495 
01496 
01497 /***********************************************************************
01498  *   SetupSetFileQueueAlternatePlatformW  (SETUPAPI.@)
01499  */
01500 BOOL WINAPI SetupSetFileQueueAlternatePlatformW(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCWSTR catalogfile)
01501 {
01502     FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_w(catalogfile));
01503     return FALSE;
01504 }
01505 
01506 
01507 /***********************************************************************
01508  *            SetupInitDefaultQueueCallback   (SETUPAPI.@)
01509  */
01510 PVOID WINAPI SetupInitDefaultQueueCallback( HWND owner )
01511 {
01512     return SetupInitDefaultQueueCallbackEx( owner, 0, 0, 0, NULL );
01513 }
01514 
01515 
01516 /***********************************************************************
01517  *            SetupInitDefaultQueueCallbackEx   (SETUPAPI.@)
01518  */
01519 PVOID WINAPI SetupInitDefaultQueueCallbackEx( HWND owner, HWND progress, UINT msg,
01520                                               DWORD reserved1, PVOID reserved2 )
01521 {
01522     struct default_callback_context *context;
01523 
01524     if ((context = HeapAlloc( GetProcessHeap(), 0, sizeof(*context) )))
01525     {
01526         context->owner    = owner;
01527         context->progress = progress;
01528         context->message  = msg;
01529     }
01530     return context;
01531 }
01532 
01533 
01534 /***********************************************************************
01535  *            SetupTermDefaultQueueCallback   (SETUPAPI.@)
01536  */
01537 void WINAPI SetupTermDefaultQueueCallback( PVOID context )
01538 {
01539     HeapFree( GetProcessHeap(), 0, context );
01540 }
01541 
01542 
01543 /***********************************************************************
01544  *            SetupDefaultQueueCallbackA   (SETUPAPI.@)
01545  */
01546 UINT WINAPI SetupDefaultQueueCallbackA( PVOID context, UINT notification,
01547                                         UINT_PTR param1, UINT_PTR param2 )
01548 {
01549     FILEPATHS_A *paths = (FILEPATHS_A *)param1;
01550     struct default_callback_context *ctx = (struct default_callback_context *)context;
01551 
01552     switch(notification)
01553     {
01554     case SPFILENOTIFY_STARTQUEUE:
01555         TRACE( "start queue\n" );
01556         return TRUE;
01557     case SPFILENOTIFY_ENDQUEUE:
01558         TRACE( "end queue\n" );
01559         return 0;
01560     case SPFILENOTIFY_STARTSUBQUEUE:
01561         TRACE( "start subqueue %ld count %ld\n", param1, param2 );
01562         return TRUE;
01563     case SPFILENOTIFY_ENDSUBQUEUE:
01564         TRACE( "end subqueue %ld\n", param1 );
01565         return 0;
01566     case SPFILENOTIFY_STARTDELETE:
01567         TRACE( "start delete %s\n", debugstr_a(paths->Target) );
01568         return FILEOP_DOIT;
01569     case SPFILENOTIFY_ENDDELETE:
01570         TRACE( "end delete %s\n", debugstr_a(paths->Target) );
01571         return 0;
01572     case SPFILENOTIFY_DELETEERROR:
01573         /*Windows Ignores attempts to delete files / folders which do not exist*/
01574         if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
01575         SetupDeleteErrorA(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
01576         return FILEOP_SKIP;
01577     case SPFILENOTIFY_STARTRENAME:
01578         TRACE( "start rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
01579         return FILEOP_DOIT;
01580     case SPFILENOTIFY_ENDRENAME:
01581         TRACE( "end rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
01582         return 0;
01583     case SPFILENOTIFY_RENAMEERROR:
01584         SetupRenameErrorA(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
01585         return FILEOP_SKIP;
01586     case SPFILENOTIFY_STARTCOPY:
01587         TRACE( "start copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
01588         return FILEOP_DOIT;
01589     case SPFILENOTIFY_ENDCOPY:
01590         TRACE( "end copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) );
01591         return 0;
01592     case SPFILENOTIFY_COPYERROR:
01593         ERR( "copy error %d %s -> %s\n", paths->Win32Error,
01594              debugstr_a(paths->Source), debugstr_a(paths->Target) );
01595         return FILEOP_SKIP;
01596     case SPFILENOTIFY_NEEDMEDIA:
01597         TRACE( "need media\n" );
01598         return FILEOP_SKIP;
01599     default:
01600         FIXME( "notification %d params %lx,%lx\n", notification, param1, param2 );
01601         break;
01602     }
01603     return 0;
01604 }
01605 
01606 
01607 /***********************************************************************
01608  *            SetupDefaultQueueCallbackW   (SETUPAPI.@)
01609  */
01610 UINT WINAPI SetupDefaultQueueCallbackW( PVOID context, UINT notification,
01611                                         UINT_PTR param1, UINT_PTR param2 )
01612 {
01613     FILEPATHS_W *paths = (FILEPATHS_W *)param1;
01614     struct default_callback_context *ctx = (struct default_callback_context *)context;
01615 
01616     switch(notification)
01617     {
01618     case SPFILENOTIFY_STARTQUEUE:
01619         TRACE( "start queue\n" );
01620         return TRUE;
01621     case SPFILENOTIFY_ENDQUEUE:
01622         TRACE( "end queue\n" );
01623         return 0;
01624     case SPFILENOTIFY_STARTSUBQUEUE:
01625         TRACE( "start subqueue %ld count %ld\n", param1, param2 );
01626         return TRUE;
01627     case SPFILENOTIFY_ENDSUBQUEUE:
01628         TRACE( "end subqueue %ld\n", param1 );
01629         return 0;
01630     case SPFILENOTIFY_STARTDELETE:
01631         TRACE( "start delete %s\n", debugstr_w(paths->Target) );
01632         return FILEOP_DOIT;
01633     case SPFILENOTIFY_ENDDELETE:
01634         TRACE( "end delete %s\n", debugstr_w(paths->Target) );
01635         return 0;
01636     case SPFILENOTIFY_DELETEERROR:
01637         /*Windows Ignores attempts to delete files / folders which do not exist*/
01638         if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND))
01639             SetupDeleteErrorW(ctx->owner, NULL, paths->Target, paths->Win32Error, 0);
01640         return FILEOP_SKIP;
01641     case SPFILENOTIFY_STARTRENAME:
01642         SetupRenameErrorW(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0);
01643         return FILEOP_DOIT;
01644     case SPFILENOTIFY_ENDRENAME:
01645         TRACE( "end rename %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
01646         return 0;
01647     case SPFILENOTIFY_RENAMEERROR:
01648         ERR( "rename error %d %s -> %s\n", paths->Win32Error,
01649              debugstr_w(paths->Source), debugstr_w(paths->Target) );
01650         return FILEOP_SKIP;
01651     case SPFILENOTIFY_STARTCOPY:
01652         TRACE( "start copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
01653         return FILEOP_DOIT;
01654     case SPFILENOTIFY_ENDCOPY:
01655         TRACE( "end copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) );
01656         return 0;
01657     case SPFILENOTIFY_COPYERROR:
01658         ERR( "copy error %d %s -> %s\n", paths->Win32Error,
01659              debugstr_w(paths->Source), debugstr_w(paths->Target) );
01660         return FILEOP_SKIP;
01661     case SPFILENOTIFY_NEEDMEDIA:
01662         TRACE( "need media\n" );
01663         return FILEOP_SKIP;
01664     default:
01665         FIXME( "notification %d params %lx,%lx\n", notification, param1, param2 );
01666         break;
01667     }
01668     return 0;
01669 }
01670 
01671 /***********************************************************************
01672  *            SetupDeleteErrorA   (SETUPAPI.@)
01673  */
01674 
01675 UINT WINAPI SetupDeleteErrorA( HWND parent, PCSTR dialogTitle, PCSTR file,
01676                                UINT w32error, DWORD style)
01677 {
01678     FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
01679            w32error, debugstr_a(file) );
01680     return DPROMPT_SKIPFILE;
01681 }
01682 
01683 /***********************************************************************
01684  *            SetupDeleteErrorW   (SETUPAPI.@)
01685  */
01686 
01687 UINT WINAPI SetupDeleteErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR file,
01688                                UINT w32error, DWORD style)
01689 {
01690     FIXME( "stub: (Error Number %d when attempting to delete %s)\n",
01691            w32error, debugstr_w(file) );
01692     return DPROMPT_SKIPFILE;
01693 }
01694 
01695 /***********************************************************************
01696  *            SetupRenameErrorA   (SETUPAPI.@)
01697  */
01698 
01699 UINT WINAPI SetupRenameErrorA( HWND parent, PCSTR dialogTitle, PCSTR source,
01700                                PCSTR target, UINT w32error, DWORD style)
01701 {
01702     FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
01703            w32error, debugstr_a(source), debugstr_a(target));
01704     return DPROMPT_SKIPFILE;
01705 }
01706 
01707 /***********************************************************************
01708  *            SetupRenameErrorW   (SETUPAPI.@)
01709  */
01710 
01711 UINT WINAPI SetupRenameErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR source,
01712                                PCWSTR target, UINT w32error, DWORD style)
01713 {
01714     FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n",
01715            w32error, debugstr_w(source), debugstr_w(target));
01716     return DPROMPT_SKIPFILE;
01717 }
01718 
01719 
01720 /***********************************************************************
01721  *            SetupCopyErrorA   (SETUPAPI.@)
01722  */
01723 
01724 UINT WINAPI SetupCopyErrorA( HWND parent, PCSTR dialogTitle, PCSTR diskname,
01725                              PCSTR sourcepath, PCSTR sourcefile, PCSTR targetpath,
01726                              UINT w32error, DWORD style, PSTR pathbuffer,
01727                              DWORD buffersize, PDWORD requiredsize)
01728 {
01729     FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
01730            w32error, debugstr_a(sourcefile), debugstr_a(sourcepath) ,debugstr_a(targetpath));
01731     return DPROMPT_SKIPFILE;
01732 }
01733 
01734 /***********************************************************************
01735  *            SetupCopyErrorW   (SETUPAPI.@)
01736  */
01737 
01738 UINT WINAPI SetupCopyErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR diskname,
01739                              PCWSTR sourcepath, PCWSTR sourcefile, PCWSTR targetpath,
01740                              UINT w32error, DWORD style, PWSTR pathbuffer,
01741                              DWORD buffersize, PDWORD requiredsize)
01742 {
01743     FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n",
01744            w32error, debugstr_w(sourcefile), debugstr_w(sourcepath) ,debugstr_w(targetpath));
01745     return DPROMPT_SKIPFILE;
01746 }
01747 
01748 /***********************************************************************
01749  *            pSetupGetQueueFlags   (SETUPAPI.@)
01750  */
01751 DWORD WINAPI pSetupGetQueueFlags( HSPFILEQ handle )
01752 {
01753     struct file_queue *queue = handle;
01754     return queue->flags;
01755 }
01756 
01757 /***********************************************************************
01758  *            pSetupSetQueueFlags   (SETUPAPI.@)
01759  */
01760 BOOL WINAPI pSetupSetQueueFlags( HSPFILEQ handle, DWORD flags )
01761 {
01762     struct file_queue *queue = handle;
01763     queue->flags = flags;
01764     return TRUE;
01765 }

Generated on Fri May 25 2012 04:24:22 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.