Raphael wrote:

Changelog:
 - semi implementation of advpack APIs LaunchINFSection/LaunchINFSectionEx
- semi implementation of advpack API ExtractFiles - setupapi: correct and check pExtractFiles return code

I have a few comments:

------------------------------------------------------------------------
@@ -91,30 +105,132 @@
}

/***********************************************************************
- *             LaunchINFSection  (ADVPACK.@)
- */
-void WINAPI LaunchINFSection( HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT 
show )
-{
-    FIXME("(%p %p %s %d): stub\n", hWnd, hInst, debugstr_a(cmdline), show );
-}
-
-/***********************************************************************
 *              LaunchINFSectionEx  (ADVPACK.@)
 */
-void WINAPI LaunchINFSectionEx( HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, 
INT show )
+static UINT LaunchINFSectionEx_CabExtractCallBackA(PVOID Context, UINT Notification, UINT_PTR Param1, UINT_PTR Param2) {
-    FIXME("(%p %p %s %d): stub\n", hWnd, hInst, debugstr_a(cmdline), show );
-}
+    LPCSTR file = (LPCSTR) Context;
+    PFILE_IN_CABINET_INFO_A pInfo = (PFILE_IN_CABINET_INFO_A) Param1;
+    if ( Notification != SPFILENOTIFY_FILEINCABINET ) return 0;
+    assert( 0 != Param1 );

Why bother with the assert? You'll crash more nicely by just dereferencing the NULL pointer. At least then you'll get a backtrace in the debugger.

+    if (0 != strcmp(file, pInfo->NameInCabinet)) return FILEOP_SKIP;
+    lstrcpyA(pInfo->FullTargetName, pInfo->NameInCabinet);
+    TRACE("Extraction of '%s'\n", pInfo->NameInCabinet);
+    return FILEOP_DOIT;
+}
+
+HRESULT WINAPI LaunchINFSectionEx( HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, 
INT show )
+{
+    CHAR inf_name[512];
+    CHAR section_name[512];
+    CHAR cab_name[512];
+    CHAR szFlags[48];
+    CHAR szShow[2];
+    DWORD dwFlags;
+ CHAR* cursor = NULL; + SIZE_T sz = 0;
+    BOOL bTest;
+    HINF hinf;
+    void* callback_context;

-/* this structure very closely resembles parameters of RunSetupCommand() */
-typedef struct
-{
-    HWND hwnd;
-    LPCSTR title;
-    LPCSTR inf_name;
-    LPCSTR dir;
-    LPCSTR section_name;
-} SETUPCOMMAND_PARAMS;
+    FIXME("(%p %p %s %d): semi-stub\n", hWnd, hInst, debugstr_a(cmdline), show 
);
+
+    cursor = strchr(cmdline, ',');
+    if (NULL == cursor) { return E_INVALIDARG; }

This is just personal preference, but the extra brackets there aren't needed and don't add to the readability and I haven't seen this style used elsewhere in the Wine source code.

+    sz = (cursor - cmdline) + 1;
+    lstrcpynA(inf_name, cmdline, sz); inf_name[sz] = 0;
+    cmdline = cursor + 1;
+
+    cursor = strchr(cmdline, ',');
+    if (NULL == cursor) { return E_INVALIDARG; }
+    sz = (cursor - cmdline) + 1;
+    lstrcpynA(section_name, cmdline, sz); section_name[sz] = 0;
+    cmdline = cursor + 1;
+
+    cursor = strchr(cmdline, ',');
+    if (NULL == cursor) { return E_INVALIDARG; }
+    sz = (cursor - cmdline) + 1;
+    lstrcpynA(cab_name, cmdline, sz); cab_name[sz] = 0;
+    cmdline = cursor + 1;
+
+    cursor = strchr(cmdline, ',');
+    if (NULL == cursor) { return E_INVALIDARG; }
+    sz = (cursor - cmdline) + 1;
+    lstrcpynA(szFlags, cmdline, sz); szFlags[sz] = 0;
+    cmdline = cursor + 1;
+
+    lstrcpynA(szShow, cmdline, 2); szShow[1] = 0;
+
+    dwFlags = atol(szFlags);
+
+    TRACE("cab name('%s')\n", cab_name);
+    TRACE("inf name('%s')\n", inf_name);
+    TRACE("inf section name('%s')\n", section_name);
+    TRACE("flags('%s','%lu')\n", szFlags, dwFlags);
+    TRACE("nShow('%s')\n", szShow);
+
+    if (dwFlags & 0x04) {
+      FIXME("dwFlags: Quiet Mode\n");
+    }
+    if (dwFlags & 0x08) {
+      FIXME("dwFlags: Don't Run GrpConv\n");
+      FIXME("Unsupported\n"); return E_NOTIMPL;
+    }
+    if (dwFlags & 16) {
+      FIXME("dwFlags: Force self-updating\n");
+      FIXME("Unsupported\n"); return E_NOTIMPL;
+    }
+    if (dwFlags & 32) {
+      FIXME("dwFlags: Backup data before install\n");
+    }
+    if (dwFlags & 64) {
+      FIXME("dwFlags: Rollback data to previous state\n");
+      /*FIXME("Unsupported\n"); return E_NOTIMPL;*/
+    }
+    if (dwFlags & 128) {
+      FIXME("dwFlags: Validate Backup data before install\n");
+      FIXME("Unsupported\n"); return E_NOTIMPL;
+    }
+    if (dwFlags & 256) {
+      FIXME("dwFlags: Rollback data to previous state\n");
+      FIXME("Unsupported\n"); return E_NOTIMPL;
+    }
+    if (dwFlags & 512) {
+      FIXME("dwFlags: Force delay of OCX registration\n");
+      FIXME("Unsupported\n"); return E_NOTIMPL;
+    }
+
+    if (0 != strcmp(cab_name, "")) {
+      FIXME("Unsupported Cab Extraction\n"); return E_NOTIMPL;

Is this left over debugging code?

+ bTest = SetupIterateCabinetA(cab_name, 0, + (PSP_FILE_CALLBACK_A) LaunchINFSectionEx_CabExtractCallBackA, + (LPVOID) inf_name);

Don't cast LaunchINFSectionEx_CabExtractCallBackA. That's a recipe for using a function with an incorrect calling convention and trashing the stack.

+      if (!bTest) return E_FAIL;

Don't use E_FAIL. Try to return a proper error code, preferably using what native returns in this circumstance by adding a test case.

+    }
+
+    hinf = SetupOpenInfFileA(inf_name, NULL, INF_STYLE_WIN4, NULL);
+    if (hinf == INVALID_HANDLE_VALUE) {
+      ERR("Failed to SetupOpenInfFileA(%s)\n", inf_name);
+      return E_FAIL;

Again, don't use E_FAIL. Also consider adding some more debugging information to the error message (like, say, the value returned by GetLastError()).

+    }
+
+    callback_context = SetupInitDefaultQueueCallback(hWnd);
+ bTest = SetupInstallFromInfSectionA(NULL, hinf, + section_name, + SPINST_ALL, + NULL, NULL, 0, + SetupDefaultQueueCallbackA, + callback_context, + NULL, NULL);
+    SetupTermDefaultQueueCallback(callback_context);
+    SetupCloseInfFile(hinf);
+
+    if (!bTest) {
+      ERR("Failed to SetupInstallFromInfSectionA(%s, %s)\n", inf_name, 
section_name);
+      return E_FAIL;

Again, don't use E_FAIL - return a proper error code.

+    }
+    return S_OK;
+}

/***********************************************************************
 *              DoInfInstall  (ADVPACK.@)
@@ -144,6 +260,15 @@
}

/***********************************************************************
+ *             LaunchINFSection  (ADVPACK.@)
+ */
+HRESULT WINAPI LaunchINFSection( HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, 
INT show )
+{
+    FIXME("(%p %p %s %d): semi-stub\n", hWnd, hInst, debugstr_a(cmdline), show 
);

Can you give us a clue as to what the difference between LaunchINFSection and LaunchINFSectionEx might be by adding a comment? If you don't know, a comment would still be appreciated saying that it should be doing something different here.

+    return LaunchINFSectionEx( hWnd, hInst, cmdline, show );
+}
+
+/***********************************************************************
 *              IsNTAdmin       (ADVPACK.@)
 */
BOOL WINAPI IsNTAdmin( DWORD reserved, PDWORD pReserved )
@@ -395,16 +520,59 @@
/***********************************************************************
 *             ExtractFiles    (ADVPACK.@)
 *
+ * @param CabName: Cabinet file path
+ * @param ExpandDir: Extraction Output Directory
+ * @param Flags: UNKNOWN
+ * @param FileList: if NULL extract all files
+ *                  else UNKNOWN
+ *

I don't think that is a c2man compatible documentation format.

 * BUGS
 *   Unimplemented
 */
+typedef struct
+{
+    DWORD Flags;
+    LPCSTR ExpandDir;
+    LPCSTR FileList;
+} ExtractFiles_CabExtractCallBackA_params_t;
+
+static UINT ExtractFiles_CabExtractCallBackA(PVOID Context, UINT Notification, UINT_PTR Param1, UINT_PTR Param2) +{
+    ExtractFiles_CabExtractCallBackA_params_t* pParams = 
(ExtractFiles_CabExtractCallBackA_params_t*) Context;
+    PFILE_IN_CABINET_INFO_A pInfo = (PFILE_IN_CABINET_INFO_A) Param1;
+    if ( Notification != SPFILENOTIFY_FILEINCABINET ) return 0;
+    assert( 0 != Param1 );
+    assert( 0 != Param2 );
+    /** stupid heuristic: waiting for better: ie. understanding what is 
FileList format */
+ if (NULL != pParams->FileList) + {
+        if (NULL == strstr(pParams->FileList, pInfo->NameInCabinet)) return 
FILEOP_SKIP;
+    }
+    lstrcpyA(pInfo->FullTargetName, pParams->ExpandDir);
+    /** we should test if pParams->ExpandDir finished with "\" but each app 
examples i found have it */
+    lstrcatA(pInfo->FullTargetName, pInfo->NameInCabinet);
+    TRACE("Extraction '%s' to '%s' (wanted Path was '%s')\n", pInfo->NameInCabinet, 
pInfo->FullTargetName, pParams->ExpandDir);
+    return FILEOP_DOIT;
+}

HRESULT WINAPI ExtractFiles ( LPCSTR CabName, LPCSTR ExpandDir, DWORD Flags,
                              LPCSTR FileList, LPVOID LReserved, DWORD Reserved)
{
- FIXME("(%p %p 0x%08lx %p %p 0x%08lx): stub\n", CabName, ExpandDir, Flags, + ExtractFiles_CabExtractCallBackA_params_t params;
+    BOOL bTest;
+
+ FIXME("(%p %p 0x%08lx %p %p 0x%08lx): semi-stub\n", CabName, ExpandDir, Flags, FileList, LReserved, Reserved);
-    return E_FAIL;
+
+    params.Flags = Flags;
+    params.ExpandDir = ExpandDir;
+ params.FileList = FileList; + + bTest = SetupIterateCabinetA(CabName, 0, + (PSP_FILE_CALLBACK_A) ExtractFiles_CabExtractCallBackA, + (LPVOID) &params);

Again, don't cast ExtractFiles_CabExtractCallBackA. Just fix up the declaration of that function if it issues a warning here.

+    if (!bTest) return E_FAIL;

Again, don't use E_FAIL.

--
Rob Shearman



Reply via email to