none
Problems with “SetupScanFileQueue” callback from SetupAPI C# RRS feed

  • Question

  • If this is in the wrong forums please move it, I'm unsure of which forum to post this question in.

    I've implemented a SetupAPI wrapper in C# that enumerates devices based on GUIDs. I have, more or less, converted the DevCon c++ example code found on MSDN to C# (Yes I know that this is a is all very painfull to do in .NET, but it's fun and a challenge, but I've been on this exact problem for weeks).

    I'm able to get all the appropriate information about a certain device, but a problem occurred when I reached the "SetupScanFileQueue" method.

    I cant seem to be able to make the "SetupScanFileQueue" to call my callback. The method returns true, so it seems to be working.

    My end goal is to get the driver files of the specific device.

    Additional information: The files appear to be added to the FileQueue correctly, I get this popup window that seems to copy the correct files.

    // create a file queue so we can look at this queue later 
                var queueHandler = SetupOpenFileQueue();
                if (queueHandler == IntPtr.Zero)
                    return false;
    
    
                // modify flags to indicate we're providing our own queue 
                var deviceInstallParams = new SP_DEVINSTALL_PARAMS();
                deviceInstallParams.cbSize = Marshal.SizeOf(deviceInstallParams);
                if (!SetupDiGetDeviceInstallParams(handle, ref devInfo, ref deviceInstallParams))
                {
                    error = Marshal.GetLastWin32Error();
                    return false;
                }
    
                // we want to add the files to the file queue, not install them! 
                deviceInstallParams.FileQueue = queueHandler;
                deviceInstallParams.Flags |= DI_NOVCP;
    
                if (!SetupDiGetDeviceInstallParams(handle, ref devInfo, ref deviceInstallParams))
                {
                    error = Marshal.GetLastWin32Error();
                    return false;
                }
    
                // now fill queue with files that are to be installed 
                // this involves all class/co-installers 
                if (!SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES, handle, ref devInfo))
                {
                    error = Marshal.GetLastWin32Error();
                    return false;
                }
    
                // we now have a list of delete/rename/copy files 
                // iterate the copy queue twice - 1st time to get # of files 
                // 2nd time to get files 
                // (WinXP has API to get # of files, but we want this to work 
                // on Win2k too) 
                var scanResult = 0;
                var count = 0;
                var callback = new PSP_FILE_CALLBACK(PSP_FILEFOUND_CALLBACK);
    
                var t = SetupScanFileQueue(queueHandler, SPQ_SCAN_USE_CALLBACK, IntPtr.Zero,
                    callback, ref count, ref scanResult);
    
                SetupDiDestroyDriverInfoList(handle, ref devInfo, SPDIT_CLASSDRIVER);
                if (queueHandler != IntPtr.Zero)
                    SetupCloseFileQueue(queueHandler);

    The definition of my Callback is as follows:

    public delegate uint PSP_FILE_CALLBACK(uint context, uint notifaction, IntPtr param1, IntPtr param2);
        public static uint PSP_FILEFOUND_CALLBACK(uint context, uint notifaction, IntPtr param1, IntPtr param2)
        {
            //This callback is never triggered
            return 0;
        }

    DllImport:

    [DllImport("setupapi.dll", SetLastError = true]
        private static extern uint SetupScanFileQueue(IntPtr QueueHandle,
                                                        int Flags, 
                                                        IntPtr Window,
                                                        PSP_FILE_CALLBACK CallbackRoutine,
                                                        int CallbackContext,
                                                        out int ScanResult
            );

    I've tried setting the CallingConvention to every choice possible as well. 

    Does anyone have any suggestions to what I'm doing wrong in the "SetupScanFileQueue" function, and why the callback is never called?

    Any help is very much appreciated!

    Wednesday, April 17, 2013 6:14 AM

All replies

  • Hi Stian,

    >>

     var t = SetupScanFileQueue(queueHandler, SPQ_SCAN_USE_CALLBACK, IntPtr.Zero,
                    callback, ref count, ref scanResult);

    Did you get any errors after the code executed?

    I mean win32 error.

    I have check the declaration:

    BOOL SetupScanFileQueue(
      __in   HSPFILEQ FileQueue,
      __in   DWORD Flags,
      __in   HWND Window,
      __in   PSP_FILE_CALLBACK CallbackRoutine,
      __in   PVOID CallbackContext,
      __out  PDWORD Result
    );

    Please try this declaration in C#:

    [DllImport("setupapi.dll", SetLastError = true]
        private static extern uint SetupScanFileQueue(IntPtr QueueHandle,
                                                        int Flags, 
                                                        IntPtr Window,
                                                        PSP_FILE_CALLBACK CallbackRoutine,
                                                        IntPtr CallbackContext,
                                                        IntPtr  ScanResult
            );

    Best regards,


    Mike Feng
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, April 18, 2013 7:47 AM
    Moderator
  • Hello Mike,

    Thanks for the reply!

    I tried the declaration you posted, and the result is the same. The PSP_FILE_CALLBACK is not being triggered.

    I do not receive any Win32 errors either, the API call seems to run fine, but it does return a value of "1". 

    For the API declaration I allocated two pointers of four bytes and used those as arguments for CallBackContext and ScanResult. MSDN says that ScanResult should be "0" when using the SPQ_SCAN_USE_CALLBACK, which it is. The CallbackContext argument, which in the DevCon example is called "count", returned with a rather random value. 

    I expected my callback to assign the "count" variable, or am I wrong? 

     
    Thursday, April 18, 2013 11:11 AM
  • Hi Stian,

    1 means "The queue passed the check and, if SPQ_SCAN_INFORM_USER was specified, the user indicated that copying is not required. The copy queue is empty and there are no elements on the delete or rename queues, so the caller can skip queue commit.

    And 

    The function returns zero if an error occurred .

    Best regards,


    Mike Feng
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Friday, April 19, 2013 2:25 PM
    Moderator
  • Hi Mike,

    Yes I am aware of what the return value, but as of my other question in my previous post (if Ive understood this correctly).

    I don't know if you've looked at the DevCon example, but before the "SetupScanFileQueue" call it says 

    // we now have a list of delete/rename/copy files 
    // iterate the copy queue twice - 1st time to get # of files 
    // 2nd time to get files 
     

    This is where I believed, by lookin at the DevCon source code, that the callback function should be called (on the first iteration of the filequeue) and that I would be able to count the driver files.

    Then again call the "SetupScanFileQueue" call with the count variable and retreive the drive files that way. Which would be the third argument in the callback function.

    Please correct me if I'm wrong. I'd really like for me to get this working.

    Again thank you for trying to give me information and helping me! I really appreciate it.

    - Stian

    Tuesday, April 23, 2013 6:35 AM